Real-time RV Lot Tracking System
Base URL: https://api.rvtrax.com/api/v1
All endpoints (except public auth) require Authorization: Bearer <jwt> or API key. Multi-tenancy is enforced via dealership_id from JWT.
Authentication: JWT (15min access + 7day refresh tokens). RBAC roles: owner, manager, sales, service, porter, viewer.
Pagination: Cursor-based (?limit=50&cursor=...). Responses include data + pagination object.
Error Format:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"details": {...},
"request_id": "req_..."
}
}Core Features Documented Here: Units, trackers, lots, geo-fencing, alerts, staging, location history, work orders.
graph TD
subgraph Hardware
T[LoRaWAN Trackers] --> G[Gateways]
G --> C[ChirpStack]
end
C --> I[IoT Ingest Service]
I --> P[Pipeline: Validate → Kalman → Zone Snap → Geofence → Broadcast]
P --> R[Redis + Postgres/TimescaleDB]
subgraph Clients
M[Mobile App] <--> WS[WebSocket]
W[Web Dashboard] <--> WS
end
WS <--> API[Fastify API]
POST /auth/login- JWT loginPOST /auth/refresh- Rotate tokensPOST /auth/logout- Invalidate refresh token
POST/GET/PATCH/DELETE /units- CRUD + search/filterGET /units/:id/location-history- TimelinePOST /units/import- CSV bulk import
POST/GET /trackers- Manage devicesPOST /trackers/:id/assign- Link to unitPOST /trackers/:id/unassign
POST/GET /lots- Lot managementPOST /lots/:id/grid- Define row/spot gridGET /lots/:id/live-positions- Current locations
POST/GET /geofences- Define zones/boundariesPOST/GET /alert-rules- Configurable rulesGET /alerts- List + acknowledge
POST/GET /staging-plans- Lot organization plansGET /staging-plans/:id/move-list- Porter tasksPOST/GET /work-orders- Service workflowsPOST/GET /recalls- VIN-based recall matching
ws://.../ws- Live location updates, alertsGET /analytics/*- Inventory, utilization, complianceGET /reports- Scheduled CSV/PDF exports
GET/POST /gateways- Hardware monitoringGET /billing- Subscription statusPOST /dms/sync- DMS integrationGET /settings/*- Dealership config, users, lots
Full Swagger UI available at /api/docs in dev.
See [The Code/README.md](The Code/README.md) and planning/DEVELOPMENT_ROADMAP.md for complete details.
| Method | Path | Description | Required Permission |
|---|---|---|---|
| POST | /api/v1/auth/register |
Register a new user account | Public |
| POST | /api/v1/auth/login |
Authenticate and receive JWT tokens | Public |
| POST | /api/v1/auth/refresh |
Refresh an expired access token | Public (valid refresh token) |
| POST | /api/v1/auth/logout |
Invalidate current refresh token | Authenticated |
| POST | /api/v1/auth/forgot-password |
Send password reset email | Public |
| POST | /api/v1/auth/reset-password |
Reset password with token | Public (valid reset token) |
| POST | /api/v1/auth/verify-email |
Verify email address with token | Public (valid verification token) |
Login Request
POST /api/v1/auth/login
{
"email": "mike.harrison@sunsetrvdealership.com",
"password": "S3cur3Pa$$w0rd!",
"dealershipSlug": "sunset-rv"
}Login Response
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMDFIWjRG...",
"refreshToken": "rt_a8f3c2e1-94b7-4d6e-b8a1-3f2c7e9d4b6a",
"expiresIn": 900,
"tokenType": "Bearer",
"user": {
"id": "usr_01HZ4FKX9QBMVT3N7PДЖА2E8",
"email": "mike.harrison@sunsetrvdealership.com",
"firstName": "Mike",
"lastName": "Harrison",
"role": "sales_manager",
"dealershipId": "dlr_01HZ3ABC123",
"permissions": [
"leads:read",
"leads:write",
"deals:read",
"deals:write",
"customers:read",
"customers:write"
],
"lastLoginAt": "2026-02-23T14:30:00Z"
}
}Refresh Token Request
POST /api/v1/auth/refresh
{
"refreshToken": "rt_a8f3c2e1-94b7-4d6e-b8a1-3f2c7e9d4b6a"
}Refresh Token Response
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMDFIWjRG...",
"refreshToken": "rt_b9e4d3f2-05c8-5e7f-c9b2-4g3d8f0e5c7b",
"expiresIn": 900,
"tokenType": "Bearer"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/users |
List users (paginated, filterable by role/status) | users:read |
| POST | /api/v1/users |
Create a new user account | users:create |
| GET | /api/v1/users/:id |
Get user details by ID | users:read |
| PATCH | /api/v1/users/:id |
Update user profile/role | users:update |
| DELETE | /api/v1/users/:id |
Soft-delete a user | users:delete |
| POST | /api/v1/users/invite |
Send invitation email to new user | users:create |
| PATCH | /api/v1/users/:id/deactivate |
Deactivate a user account | users:update |
| PATCH | /api/v1/users/:id/reactivate |
Reactivate a deactivated user | users:update |
| GET | /api/v1/users/me |
Get current authenticated user profile | Authenticated |
| PATCH | /api/v1/users/me |
Update own profile | Authenticated |
| PATCH | /api/v1/users/me/password |
Change own password | Authenticated |
Create User Request
POST /api/v1/users
{
"email": "jenny.cole@sunsetrvdealership.com",
"firstName": "Jenny",
"lastName": "Cole",
"phone": "+15551234567",
"roleId": "role_sales_consultant",
"departmentIds": ["dept_sales"],
"notifyByEmail": true
}Create User Response
{
"id": "usr_01HZ5GNR8TCBW4X2K9PLA3F7",
"email": "jenny.cole@sunsetrvdealership.com",
"firstName": "Jenny",
"lastName": "Cole",
"phone": "+15551234567",
"role": {
"id": "role_sales_consultant",
"name": "Sales Consultant"
},
"status": "pending_verification",
"dealershipId": "dlr_01HZ3ABC123",
"createdAt": "2026-02-23T09:15:00Z"
}List Users Request
GET /api/v1/users?page=1&limit=10&role=sales_consultant&status=active
List Users Response
{
"data": [
{
"id": "usr_01HZ4FKX9QBMVT3N7PA2E8",
"email": "mike.harrison@sunsetrvdealership.com",
"firstName": "Mike",
"lastName": "Harrison",
"role": { "id": "role_sales_manager", "name": "Sales Manager" },
"status": "active",
"lastLoginAt": "2026-02-23T14:30:00Z"
}
],
"meta": { "page": 1, "limit": 10, "total": 14, "totalPages": 2 }
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/roles |
List all roles | roles:read |
| POST | /api/v1/roles |
Create a custom role | roles:create |
| GET | /api/v1/roles/:id |
Get role details with permissions | roles:read |
| PATCH | /api/v1/roles/:id |
Update role name or permissions | roles:update |
| DELETE | /api/v1/roles/:id |
Delete a custom role | roles:delete |
| GET | /api/v1/roles/:id/users |
List users assigned to a role | roles:read |
| GET | /api/v1/permissions |
List all available permissions | roles:read |
Create Role Request
POST /api/v1/roles
{
"name": "BDC Agent",
"description": "Business Development Center agent handling inbound leads and appointment setting",
"permissions": [
"leads:read", "leads:write",
"customers:read",
"appointments:read", "appointments:write",
"communications:read", "communications:write",
"tasks:read", "tasks:write"
]
}Create Role Response
{
"id": "role_01HZ6KPQ2RBDC",
"name": "BDC Agent",
"description": "Business Development Center agent handling inbound leads and appointment setting",
"isSystem": false,
"permissions": [
"leads:read",
"leads:write",
"customers:read",
"appointments:read",
"appointments:write",
"communications:read",
"communications:write",
"tasks:read",
"tasks:write"
],
"userCount": 0,
"createdAt": "2026-02-23T10:00:00Z"
}List Permissions Response
{
"data": [
{ "key": "leads:read", "category": "Leads", "description": "View leads and pipeline" },
{ "key": "leads:write", "category": "Leads", "description": "Create and update leads" },
{ "key": "deals:read", "category": "Deals", "description": "View deal jackets" },
{ "key": "deals:write", "category": "Deals", "description": "Create and modify deals" },
{ "key": "vehicles:read", "category": "Inventory", "description": "View vehicle inventory" },
{ "key": "vehicles:write", "category": "Inventory", "description": "Manage vehicle inventory" },
{ "key": "service-orders:read", "category": "Service", "description": "View service orders" },
{ "key": "service-orders:write", "category": "Service", "description": "Manage service orders" }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/settings |
Get all dealership settings | settings:read |
| PATCH | /api/v1/settings |
Update settings (partial) | settings:update |
| GET | /api/v1/settings/:category |
Get settings by category | settings:read |
| GET | /api/v1/notification-preferences |
Get current user notification preferences | Authenticated |
| PATCH | /api/v1/notification-preferences |
Update notification preferences | Authenticated |
| GET | /api/v1/audit-logs |
List audit log entries (paginated, filtered) | audit-logs:read |
| GET | /api/v1/dealership |
Get dealership profile | settings:read |
| PATCH | /api/v1/dealership |
Update dealership profile | settings:update |
| POST | /api/v1/dealership/logo |
Upload dealership logo (multipart) | settings:update |
| GET | /api/v1/business-hours |
Get business hours configuration | settings:read |
| PATCH | /api/v1/business-hours |
Update business hours | settings:update |
Update Dealership Request
PATCH /api/v1/dealership
{
"name": "Sunset RV & Marine",
"address": {
"street": "4520 Highway 101 South",
"city": "Gold Beach",
"state": "OR",
"zip": "97444"
},
"phone": "+15412471234",
"website": "https://sunsetrv.com",
"taxRate": 0.0,
"docFee": 399.00,
"timezone": "America/Los_Angeles"
}Audit Logs Request
GET /api/v1/audit-logs?page=1&limit=25&userId=usr_01HZ4FKX9Q&action=deal.status_change&from=2026-02-01&to=2026-02-23
Audit Logs Response
{
"data": [
{
"id": "log_01HZ8ABC123",
"userId": "usr_01HZ4FKX9Q",
"userName": "Mike Harrison",
"action": "deal.status_change",
"entityType": "deal",
"entityId": "deal_01HZ7XYZ456",
"changes": {
"status": { "from": "pending_finance", "to": "approved" }
},
"ipAddress": "73.15.22.140",
"timestamp": "2026-02-22T16:45:00Z"
}
],
"meta": { "page": 1, "limit": 25, "total": 87, "totalPages": 4 }
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/customers |
Search/filter/paginate customers | customers:read |
| POST | /api/v1/customers |
Create a new customer record | customers:create |
| GET | /api/v1/customers/:id |
Get customer 360-degree view | customers:read |
| PATCH | /api/v1/customers/:id |
Update customer information | customers:update |
| DELETE | /api/v1/customers/:id |
Soft-delete a customer | customers:delete |
| GET | /api/v1/customers/:id/interactions |
List customer interaction history | customers:read |
| POST | /api/v1/customers/:id/interactions |
Log a customer interaction | customers:update |
| GET | /api/v1/customers/:id/vehicles |
List vehicles owned by customer | customers:read |
| POST | /api/v1/customers/:id/vehicles |
Link a vehicle to customer | customers:update |
| GET | /api/v1/customers/:id/documents |
List customer documents | customers:read |
| POST | /api/v1/customers/:id/documents |
Upload a document (multipart) | customers:update |
| DELETE | /api/v1/customers/:id/documents/:docId |
Remove a customer document | customers:update |
| GET | /api/v1/customers/:id/deals |
List customer deal history | customers:read |
| GET | /api/v1/customers/:id/service-orders |
List customer service history | customers:read |
| POST | /api/v1/customers/merge |
Merge duplicate customer records | customers:delete |
| GET | /api/v1/customers/duplicates |
Find potential duplicate customers | customers:read |
| POST | /api/v1/customers/:id/credit-app |
Submit credit application | customers:update |
| GET | /api/v1/customers/:id/tags |
List tags on a customer | customers:read |
| POST | /api/v1/customers/:id/tags |
Add a tag to a customer | customers:update |
| DELETE | /api/v1/customers/:id/tags/:tag |
Remove a tag from a customer | customers:update |
| GET | /api/v1/customers/export |
Export customers as CSV/XLSX | customers:export |
Customer 360 View Response
GET /api/v1/customers/cust_01HZ5RVT789
{
"id": "cust_01HZ5RVT789",
"firstName": "Dave",
"lastName": "Kowalski",
"email": "dave.kowalski@gmail.com",
"phone": "+15039876543",
"address": {
"street": "1287 Pine Crest Lane",
"city": "Bend",
"state": "OR",
"zip": "97701"
},
"customerType": "retail",
"source": "rv_show",
"tags": ["repeat_buyer", "full_timer", "financing_preferred"],
"lifetimeValue": 287450.00,
"creditScore": 742,
"preferredContact": "phone",
"stats": {
"totalDeals": 3,
"totalServiceOrders": 7,
"totalSpent": 287450.00,
"averageDealValue": 95816.67,
"lastPurchaseDate": "2025-06-14T00:00:00Z",
"lastServiceDate": "2026-01-18T00:00:00Z",
"openLeads": 1,
"pendingAppointments": 1
},
"recentInteractions": [
{
"id": "int_01HZ9AAA111",
"type": "phone_call",
"direction": "outbound",
"summary": "Discussed 2026 Winnebago View 24V availability. Customer interested in trading 2023 Navion.",
"userId": "usr_01HZ4FKX9Q",
"userName": "Mike Harrison",
"timestamp": "2026-02-22T10:30:00Z"
}
],
"vehicles": [
{
"id": "veh_01HZ6WXY456",
"year": 2023,
"make": "Winnebago",
"model": "Navion 24V",
"vin": "5B4MP67G1X3456789",
"relationship": "owner",
"purchaseDate": "2023-03-20T00:00:00Z"
}
],
"openDeals": [
{
"id": "deal_01HZ7XYZ456",
"status": "pending_finance",
"vehicleDescription": "2026 Winnebago View 24V",
"salePrice": 162500.00,
"createdAt": "2026-02-20T00:00:00Z"
}
],
"upcomingAppointments": [
{
"id": "appt_01HZ8BCD789",
"type": "test_drive",
"scheduledAt": "2026-02-25T14:00:00Z",
"with": "Mike Harrison"
}
],
"createdAt": "2022-09-10T00:00:00Z",
"updatedAt": "2026-02-22T10:35:00Z"
}Create Customer Request
POST /api/v1/customers
{
"firstName": "Sarah",
"lastName": "Mitchell",
"email": "sarah.mitchell@outlook.com",
"phone": "+15417654321",
"address": {
"street": "890 Redwood Drive",
"city": "Medford",
"state": "OR",
"zip": "97501"
},
"customerType": "retail",
"source": "website",
"preferredContact": "email",
"tags": ["first_time_buyer"],
"notes": "Interested in Class B motorhomes for weekend trips."
}Create Customer Response
{
"id": "cust_01HZ9NEW001",
"firstName": "Sarah",
"lastName": "Mitchell",
"email": "sarah.mitchell@outlook.com",
"phone": "+15417654321",
"customerType": "retail",
"source": "website",
"tags": ["first_time_buyer"],
"lifetimeValue": 0,
"createdAt": "2026-02-23T11:00:00Z"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/leads |
List leads with pipeline view | leads:read |
| POST | /api/v1/leads |
Create a new lead | leads:create |
| GET | /api/v1/leads/:id |
Get lead details | leads:read |
| PATCH | /api/v1/leads/:id |
Update lead information | leads:update |
| DELETE | /api/v1/leads/:id |
Delete a lead | leads:delete |
| PATCH | /api/v1/leads/:id/stage |
Move lead to a different pipeline stage | leads:update |
| POST | /api/v1/leads/:id/assign |
Assign lead to a salesperson | leads:assign |
| GET | /api/v1/leads/pipeline-stats |
Get pipeline statistics and conversion rates | leads:read |
| GET | /api/v1/leads/sources |
List lead sources with counts | leads:read |
| POST | /api/v1/leads/import |
Bulk import leads from CSV | leads:create |
Pipeline Stats Response
GET /api/v1/leads/pipeline-stats?from=2026-02-01&to=2026-02-23
{
"totalLeads": 147,
"totalValue": 8745000.00,
"conversionRate": 0.184,
"averageDaysToClose": 18.3,
"stages": [
{ "stage": "new", "count": 42, "value": 2520000.00, "avgAge": 1.2 },
{ "stage": "contacted", "count": 31, "value": 1860000.00, "avgAge": 3.8 },
{ "stage": "qualified", "count": 28, "value": 1960000.00, "avgAge": 7.1 },
{ "stage": "demo_scheduled", "count": 15, "value": 1125000.00, "avgAge": 9.4 },
{ "stage": "proposal", "count": 12, "value": 1020000.00, "avgAge": 12.6 },
{ "stage": "negotiation", "count": 8, "value": 640000.00, "avgAge": 15.2 },
{ "stage": "won", "count": 27, "value": 2430000.00, "avgAge": 18.3 },
{ "stage": "lost", "count": 19, "value": 1140000.00, "avgAge": 14.7 }
],
"bySource": [
{ "source": "website", "count": 52, "conversionRate": 0.21 },
{ "source": "rv_show", "count": 34, "conversionRate": 0.29 },
{ "source": "referral", "count": 23, "conversionRate": 0.35 },
{ "source": "rv_trader", "count": 18, "conversionRate": 0.11 },
{ "source": "facebook", "count": 12, "conversionRate": 0.08 },
{ "source": "walk_in", "count": 8, "conversionRate": 0.50 }
],
"byAssignee": [
{ "userId": "usr_01HZ4FKX9Q", "name": "Mike Harrison", "count": 38, "wonCount": 9, "conversionRate": 0.237 },
{ "userId": "usr_01HZ5GNR8T", "name": "Jenny Cole", "count": 32, "wonCount": 7, "conversionRate": 0.219 }
]
}Create Lead Request
POST /api/v1/leads
{
"customerId": "cust_01HZ9NEW001",
"source": "website",
"stage": "new",
"interestType": "purchase",
"vehicleInterest": {
"type": "class_b",
"makes": ["Winnebago", "Pleasure-Way"],
"budgetMin": 120000,
"budgetMax": 180000,
"newOrUsed": "either"
},
"notes": "Submitted web form requesting Class B info for weekend camping.",
"assignToId": "usr_01HZ4FKX9Q"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/tasks |
List tasks with filters | tasks:read |
| POST | /api/v1/tasks |
Create a new task | tasks:create |
| GET | /api/v1/tasks/:id |
Get task details | tasks:read |
| PATCH | /api/v1/tasks/:id |
Update a task | tasks:update |
| DELETE | /api/v1/tasks/:id |
Delete a task | tasks:delete |
| PATCH | /api/v1/tasks/:id/complete |
Mark task as completed | tasks:update |
| GET | /api/v1/tasks/overdue |
List all overdue tasks | tasks:read |
| GET | /api/v1/tasks/my-tasks |
List tasks assigned to current user | Authenticated |
Create Task Request
POST /api/v1/tasks
{
"title": "Follow up with Dave Kowalski on View 24V trade-in appraisal",
"description": "Dave is expecting a call back with the trade-in value for his 2023 Navion 24V. Get appraisal from Mike in service first.",
"type": "follow_up",
"priority": "high",
"dueAt": "2026-02-24T10:00:00Z",
"assignToId": "usr_01HZ4FKX9Q",
"relatedEntityType": "customer",
"relatedEntityId": "cust_01HZ5RVT789"
}My Tasks Response
GET /api/v1/tasks/my-tasks?status=pending&sort=dueAt
{
"data": [
{
"id": "task_01HZ9T001",
"title": "Follow up with Dave Kowalski on View 24V trade-in appraisal",
"type": "follow_up",
"priority": "high",
"status": "pending",
"dueAt": "2026-02-24T10:00:00Z",
"relatedEntity": { "type": "customer", "id": "cust_01HZ5RVT789", "name": "Dave Kowalski" },
"createdAt": "2026-02-23T09:00:00Z"
},
{
"id": "task_01HZ9T002",
"title": "Send RV show follow-up emails to Portland Expo leads",
"type": "campaign",
"priority": "medium",
"status": "pending",
"dueAt": "2026-02-25T09:00:00Z",
"relatedEntity": { "type": "rv_show", "id": "show_01HZ7RVS001", "name": "Portland RV & Outdoor Show 2026" },
"createdAt": "2026-02-23T08:00:00Z"
}
],
"meta": { "page": 1, "limit": 25, "total": 12, "totalPages": 1 }
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/appointments |
List appointments with filters | appointments:read |
| POST | /api/v1/appointments |
Create an appointment | appointments:create |
| GET | /api/v1/appointments/:id |
Get appointment details | appointments:read |
| PATCH | /api/v1/appointments/:id |
Update an appointment | appointments:update |
| DELETE | /api/v1/appointments/:id |
Delete an appointment | appointments:delete |
| PATCH | /api/v1/appointments/:id/cancel |
Cancel an appointment with reason | appointments:update |
| PATCH | /api/v1/appointments/:id/confirm |
Confirm an appointment | appointments:update |
| GET | /api/v1/appointments/availability |
Get available time slots | appointments:read |
| GET | /api/v1/appointments/calendar |
Get calendar view of appointments | appointments:read |
Create Appointment Request
POST /api/v1/appointments
{
"customerId": "cust_01HZ5RVT789",
"type": "test_drive",
"title": "Test Drive - 2026 Winnebago View 24V",
"scheduledAt": "2026-02-25T14:00:00Z",
"duration": 90,
"assignToId": "usr_01HZ4FKX9Q",
"vehicleId": "veh_01HZ6ABC789",
"notes": "Customer wants to drive on Highway 97 to test hill performance. Ensure coach is fueled and leveled.",
"sendReminder": true,
"reminderMinutesBefore": 60
}Availability Response
GET /api/v1/appointments/availability?date=2026-02-25&type=test_drive&userId=usr_01HZ4FKX9Q
{
"date": "2026-02-25",
"userId": "usr_01HZ4FKX9Q",
"userName": "Mike Harrison",
"timezone": "America/Los_Angeles",
"slots": [
{ "start": "09:00", "end": "10:30", "available": true },
{ "start": "10:30", "end": "12:00", "available": true },
{ "start": "12:00", "end": "13:00", "available": false, "reason": "lunch_block" },
{ "start": "13:00", "end": "14:30", "available": false, "reason": "existing_appointment" },
{ "start": "14:30", "end": "16:00", "available": true },
{ "start": "16:00", "end": "17:30", "available": true }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/vehicles |
List vehicles with 20+ filters | vehicles:read |
| POST | /api/v1/vehicles |
Add a vehicle to inventory | vehicles:create |
| GET | /api/v1/vehicles/:id |
Get vehicle details | vehicles:read |
| PATCH | /api/v1/vehicles/:id |
Update vehicle information | vehicles:update |
| DELETE | /api/v1/vehicles/:id |
Archive a vehicle | vehicles:delete |
| POST | /api/v1/vehicles/:id/photos |
Upload photos (multipart, up to 50) | vehicles:update |
| PATCH | /api/v1/vehicles/:id/photos/reorder |
Reorder vehicle photos | vehicles:update |
| DELETE | /api/v1/vehicles/:id/photos/:photoId |
Delete a vehicle photo | vehicles:update |
| POST | /api/v1/vehicles/:id/costs |
Add a cost/recon entry | vehicles:update |
| GET | /api/v1/vehicles/:id/costs |
List vehicle costs | vehicles:read |
| GET | /api/v1/vehicles/:id/history |
Get vehicle history (ownership, service) | vehicles:read |
| GET | /api/v1/vehicles/decode/:vin |
Decode VIN and return specs | vehicles:read |
| GET | /api/v1/vehicles/stats |
Get inventory statistics | vehicles:read |
| GET | /api/v1/vehicles/search |
Full-text search across inventory | vehicles:read |
| POST | /api/v1/vehicles/import |
Bulk import vehicles from CSV | vehicles:create |
| GET | /api/v1/vehicles/export |
Export inventory as CSV/XLSX | vehicles:export |
| GET | /api/v1/vehicles/similar/:id |
Find similar vehicles in inventory | vehicles:read |
VIN Decode Response
GET /api/v1/vehicles/decode/1FTNW21F3YEA12345
{
"vin": "1FTNW21F3YEA12345",
"valid": true,
"year": 2026,
"make": "Thor Motor Coach",
"model": "Gemini 23TW",
"trim": "AWD",
"bodyClass": "Class B+",
"driveType": "AWD",
"engineCylinders": 4,
"engineDisplacement": 2.0,
"engineHP": 250,
"fuelType": "Gasoline",
"transmission": "10-Speed Automatic",
"chassisMake": "Ford",
"chassisModel": "Transit 350",
"gvwr": 10360,
"gvwrClass": "Class 3",
"sleeps": 4,
"length": "24'2\"",
"manufacturerCountry": "United States",
"plantCity": "Wakarusa",
"plantState": "IN"
}Create Vehicle Request
POST /api/v1/vehicles
{
"vin": "1FTNW21F3YEA12345",
"stockNumber": "N26-0142",
"year": 2026,
"make": "Thor Motor Coach",
"model": "Gemini 23TW",
"trim": "AWD",
"condition": "new",
"status": "in_stock",
"bodyType": "class_b_plus",
"msrp": 142950.00,
"invoiceCost": 121507.50,
"askingPrice": 139995.00,
"mileage": 12,
"exteriorColor": "Silver Spruce",
"interiorColor": "Coastal Gray",
"fuelType": "gasoline",
"length": 24.2,
"sleeps": 4,
"slideouts": 0,
"features": [
"Murphy bed", "Onan 4.0kW generator", "15K BTU A/C",
"Tankless water heater", "Solar panel prep", "Hydraulic leveling jacks"
],
"lotId": "lot_main",
"location": "Row C, Space 14"
}Create Vehicle Response
{
"id": "veh_01HZ9VEH001",
"vin": "1FTNW21F3YEA12345",
"stockNumber": "N26-0142",
"year": 2026,
"make": "Thor Motor Coach",
"model": "Gemini 23TW",
"trim": "AWD",
"condition": "new",
"status": "in_stock",
"bodyType": "class_b_plus",
"msrp": 142950.0,
"invoiceCost": 121507.5,
"askingPrice": 139995.0,
"mileage": 12,
"daysInStock": 0,
"photoCount": 0,
"lotId": "lot_main",
"location": "Row C, Space 14",
"createdAt": "2026-02-23T11:30:00Z"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| POST | /api/v1/deals |
Create a new deal | deals:create |
| GET | /api/v1/deals |
List deals with filters | deals:read |
| GET | /api/v1/deals/:id |
Get full deal jacket | deals:read |
| PATCH | /api/v1/deals/:id |
Update deal details | deals:update |
| PATCH | /api/v1/deals/:id/status |
Change deal status | deals:update |
| POST | /api/v1/deals/:id/fi-products |
Add F&I product to deal | deals:update |
| DELETE | /api/v1/deals/:id/fi-products/:productId |
Remove F&I product | deals:update |
| PATCH | /api/v1/deals/:id/fi-products/:productId |
Update F&I product details | deals:update |
| POST | /api/v1/deals/:id/calculate |
Calculate payments for deal | deals:read |
| POST | /api/v1/deals/:id/trade-in |
Add trade-in vehicle to deal | deals:update |
| DELETE | /api/v1/deals/:id/trade-in |
Remove trade-in from deal | deals:update |
| GET | /api/v1/deals/:id/documents |
List deal documents | deals:read |
| POST | /api/v1/deals/:id/documents/generate |
Generate deal documents (PDF) | deals:update |
| GET | /api/v1/deals/stats |
Get deal statistics | deals:read |
| GET | /api/v1/deals/:id/profit-analysis |
Get deal profit breakdown | deals:read_profit |
| PATCH | /api/v1/deals/:id/cancel |
Cancel a deal | deals:cancel |
| POST | /api/v1/deals/:id/unwind |
Unwind a completed deal | deals:unwind |
Payment Calculator Response
POST /api/v1/deals/deal_01HZ7XYZ456/calculate
{
"dealId": "deal_01HZ7XYZ456",
"vehiclePrice": 162500.00,
"fiProducts": [
{ "name": "Extended Warranty - 7yr/100K", "price": 3495.00, "cost": 1200.00 },
{ "name": "Tire & Wheel Protection", "price": 1295.00, "cost": 340.00 },
{ "name": "Paint & Fabric Protection", "price": 995.00, "cost": 175.00 }
],
"fiTotal": 5785.00,
"tradeIn": {
"vehicleId": "veh_01HZ6WXY456",
"description": "2023 Winnebago Navion 24V",
"allowance": 95000.00,
"payoff": 42000.00,
"netTradeEquity": 53000.00
},
"subtotal": 115285.00,
"docFee": 399.00,
"salesTax": 0.00,
"registrationFees": 345.00,
"totalDue": 116029.00,
"downPayment": 20000.00,
"amountFinanced": 96029.00,
"scenarios": [
{
"term": 180,
"apr": 6.99,
"monthlyPayment": 863.42,
"totalInterest": 59386.60,
"totalOfPayments": 155415.60,
"lender": "US Bank RV Lending"
},
{
"term": 240,
"apr": 7.49,
"monthlyPayment": 774.21,
"totalInterest": 89781.40,
"totalOfPayments": 185810.40,
"lender": "US Bank RV Lending"
},
{
"term": 180,
"apr": 7.49,
"monthlyPayment": 888.17,
"totalInterest": 63841.60,
"totalOfPayments": 159870.60,
"lender": "Good Sam Finance"
}
]
}Create Deal Request
POST /api/v1/deals
{
"customerId": "cust_01HZ5RVT789",
"vehicleId": "veh_01HZ6ABC789",
"salesPersonId": "usr_01HZ4FKX9Q",
"dealType": "retail_finance",
"salePrice": 162500.00,
"downPayment": 20000.00,
"leadId": "lead_01HZ6LPQ456"
}Deal Profit Analysis Response
GET /api/v1/deals/deal_01HZ7XYZ456/profit-analysis
{
"dealId": "deal_01HZ7XYZ456",
"frontEndProfit": {
"salePrice": 162500.00,
"invoiceCost": 138125.00,
"holdback": 4143.75,
"reconCosts": 1250.00,
"advertising": 500.00,
"netFrontEnd": 26768.75
},
"backEndProfit": {
"fiProducts": [
{ "name": "Extended Warranty - 7yr/100K", "revenue": 3495.00, "cost": 1200.00, "profit": 2295.00 },
{ "name": "Tire & Wheel Protection", "revenue": 1295.00, "cost": 340.00, "profit": 955.00 },
{ "name": "Paint & Fabric Protection", "revenue": 995.00, "cost": 175.00, "profit": 820.00 }
],
"financeReserve": 1920.58,
"docFee": 399.00,
"netBackEnd": 6389.58
},
"tradeProfit": {
"tradeAllowance": 95000.00,
"estimatedACV": 91000.00,
"overAllowance": -4000.00
},
"totalGrossProfit": 29158.33,
"commissionable": 29158.33,
"salesPersonCommission": 7289.58,
"dealRating": "A"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/consignments |
List consignment agreements | consignments:read |
| POST | /api/v1/consignments |
Create a consignment agreement | consignments:create |
| GET | /api/v1/consignments/:id |
Get consignment details | consignments:read |
| PATCH | /api/v1/consignments/:id |
Update consignment terms | consignments:update |
| POST | /api/v1/consignments/:id/settle |
Settle/close a consignment after sale | consignments:settle |
| GET | /api/v1/consignments/:id/statement |
Generate consignor statement | consignments:read |
| GET | /api/v1/consignments/stats |
Get consignment portfolio stats | consignments:read |
Create Consignment Request
POST /api/v1/consignments
{
"consignorId": "cust_01HZ5CCC001",
"vehicleId": "veh_01HZ9CNS001",
"minimumPrice": 68000.00,
"targetPrice": 74900.00,
"commissionType": "percentage",
"commissionRate": 10.0,
"agreementStartDate": "2026-02-23",
"agreementEndDate": "2026-05-23",
"terms": "Consignor responsible for insurance until sale. Dealer handles all marketing and showing. 30-day payout after closing."
}Consignment Stats Response
GET /api/v1/consignments/stats
{
"activeConsignments": 8,
"totalListValue": 623500.00,
"averageDaysOnLot": 34,
"soldThisMonth": 2,
"revenueThisMonth": 14250.00,
"expiringSoon": 1,
"byType": [
{ "type": "motorhome", "count": 5, "value": 478000.00 },
{ "type": "travel_trailer", "count": 2, "value": 98500.00 },
{ "type": "fifth_wheel", "count": 1, "value": 47000.00 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/floor-plans |
List floor plan lines | floor-plans:read |
| POST | /api/v1/floor-plans |
Create a floor plan line | floor-plans:create |
| GET | /api/v1/floor-plans/:id |
Get floor plan details | floor-plans:read |
| PATCH | /api/v1/floor-plans/:id |
Update floor plan terms | floor-plans:update |
| POST | /api/v1/floor-plans/:id/vehicles |
Add vehicle to floor plan | floor-plans:update |
| PATCH | /api/v1/floor-plans/:id/vehicles/:vid |
Update vehicle floor plan status | floor-plans:update |
| DELETE | /api/v1/floor-plans/:id/vehicles/:vid |
Pay off and remove vehicle from floor plan | floor-plans:update |
| POST | /api/v1/floor-plans/:id/accrue |
Run interest accrual for the period | floor-plans:accrue |
| GET | /api/v1/floor-plans/:id/audit |
Get floor plan audit trail | floor-plans:read |
| POST | /api/v1/floor-plans/:id/audit |
Record a floor plan audit/count | floor-plans:audit |
| GET | /api/v1/floor-plans/exposure-summary |
Get total floor plan exposure across all lines | floor-plans:read |
Exposure Summary Response
GET /api/v1/floor-plans/exposure-summary
{
"totalCreditLine": 3500000.00,
"totalOutstanding": 2187500.00,
"totalAvailable": 1312500.00,
"utilizationRate": 0.625,
"totalAccruedInterest": 14875.00,
"vehiclesOnPlan": 28,
"averageDaysOnPlan": 47,
"lines": [
{
"id": "fp_01HZ6FP001",
"lender": "NextGear Capital",
"creditLine": 2000000.00,
"outstanding": 1425000.00,
"available": 575000.00,
"rate": 8.25,
"vehicleCount": 18,
"avgDaysOnPlan": 42
},
{
"id": "fp_01HZ6FP002",
"lender": "TCF Floorplan",
"creditLine": 1500000.00,
"outstanding": 762500.00,
"available": 737500.00,
"rate": 7.99,
"vehicleCount": 10,
"avgDaysOnPlan": 55
}
],
"agingBuckets": [
{ "bucket": "0-30 days", "count": 8, "value": 625000.00 },
{ "bucket": "31-60 days", "count": 10, "value": 787500.00 },
{ "bucket": "61-90 days", "count": 6, "value": 475000.00 },
{ "bucket": "90+ days", "count": 4, "value": 300000.00 }
]
}Add Vehicle to Floor Plan Request
POST /api/v1/floor-plans/fp_01HZ6FP001/vehicles
{
"vehicleId": "veh_01HZ9VEH001",
"fundedAmount": 121507.50,
"fundedDate": "2026-02-23",
"curtailmentSchedule": [
{ "daysOnPlan": 90, "paymentPercent": 10 },
{ "daysOnPlan": 180, "paymentPercent": 15 },
{ "daysOnPlan": 270, "paymentPercent": 25 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/storage/lots |
List storage lots | storage:read |
| POST | /api/v1/storage/lots |
Create a storage lot | storage:create |
| GET | /api/v1/storage/lots/:id |
Get lot details | storage:read |
| PATCH | /api/v1/storage/lots/:id |
Update lot information | storage:update |
| GET | /api/v1/storage/contracts |
List storage contracts | storage:read |
| POST | /api/v1/storage/contracts |
Create a storage contract | storage:create |
| GET | /api/v1/storage/contracts/:id |
Get contract details | storage:read |
| PATCH | /api/v1/storage/contracts/:id |
Update storage contract | storage:update |
| POST | /api/v1/storage/contracts/:id/bill |
Generate billing for a contract period | storage:billing |
| POST | /api/v1/storage/contracts/:id/terminate |
Terminate a storage contract | storage:update |
| GET | /api/v1/storage/availability |
Get available spaces across all lots | storage:read |
| GET | /api/v1/storage/occupancy |
Get occupancy metrics | storage:read |
Create Storage Contract Request
POST /api/v1/storage/contracts
{
"customerId": "cust_01HZ5RVT789",
"vehicleDescription": "2023 Winnebago Navion 24V",
"vin": "5B4MP67G1X3456789",
"lotId": "lot_overflow_a",
"spaceNumber": "B-22",
"storageType": "outdoor_covered",
"rateType": "monthly",
"rate": 175.00,
"startDate": "2026-03-01",
"autoRenew": true,
"requireInsurance": true,
"insurancePolicyNumber": "RV-2026-44821",
"notes": "Customer keeping Navion while deciding on new purchase."
}Occupancy Response
GET /api/v1/storage/occupancy
{
"totalSpaces": 120,
"occupied": 94,
"available": 26,
"occupancyRate": 0.783,
"monthlyRevenue": 16450.00,
"byLot": [
{ "lotId": "lot_main", "name": "Main Lot", "total": 60, "occupied": 52, "type": "outdoor_open" },
{ "lotId": "lot_overflow_a", "name": "Overflow A - Covered", "total": 40, "occupied": 35, "type": "outdoor_covered" },
{ "lotId": "lot_indoor", "name": "Indoor Storage", "total": 20, "occupied": 7, "type": "indoor_heated" }
],
"byType": [
{ "type": "outdoor_open", "rate": 95.00, "count": 52, "revenue": 4940.00 },
{ "type": "outdoor_covered", "rate": 175.00, "count": 35, "revenue": 6125.00 },
{ "type": "indoor_heated", "rate": 385.00, "count": 7, "revenue": 2695.00 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/pdi/templates |
List PDI checklist templates | pdi:read |
| POST | /api/v1/pdi/templates |
Create a PDI template | pdi:create |
| GET | /api/v1/pdi/templates/:id |
Get template details with items | pdi:read |
| PATCH | /api/v1/pdi/templates/:id |
Update a PDI template | pdi:update |
| POST | /api/v1/pdi/templates/:id/clone |
Clone an existing template | pdi:create |
| GET | /api/v1/pdi/inspections |
List PDI inspections | pdi:read |
| POST | /api/v1/pdi/inspections |
Start a new PDI inspection | pdi:create |
| GET | /api/v1/pdi/inspections/:id |
Get inspection details | pdi:read |
| PATCH | /api/v1/pdi/inspections/:id/items/:itemId |
Update an inspection line item result | pdi:update |
| POST | /api/v1/pdi/inspections/:id/complete |
Mark inspection as complete | pdi:update |
| GET | /api/v1/pdi/inspections/:id/report |
Generate PDI report (PDF) | pdi:read |
| GET | /api/v1/pdi/stats |
Get PDI completion statistics | pdi:read |
Start PDI Inspection Request
POST /api/v1/pdi/inspections
{
"vehicleId": "veh_01HZ9VEH001",
"templateId": "pdi_tpl_class_b_plus",
"technicianId": "tech_01HZ8TCH002",
"priority": "high",
"notes": "Unit sold to Dave Kowalski. Delivery scheduled 2/28. Ensure all coach systems tested."
}PDI Stats Response
GET /api/v1/pdi/stats?from=2026-02-01&to=2026-02-23
{
"totalInspections": 14,
"completed": 11,
"inProgress": 2,
"failed": 1,
"averageCompletionTime": 4.2,
"issuesFound": 23,
"issuesResolved": 19,
"byCategory": [
{ "category": "Electrical Systems", "issueCount": 6, "resolvedCount": 5 },
{ "category": "Plumbing", "issueCount": 4, "resolvedCount": 4 },
{ "category": "LP Gas System", "issueCount": 3, "resolvedCount": 3 },
{ "category": "Appliances", "issueCount": 5, "resolvedCount": 4 },
{ "category": "Exterior/Structural", "issueCount": 3, "resolvedCount": 2 },
{ "category": "Chassis/Drivetrain", "issueCount": 2, "resolvedCount": 1 }
],
"byTemplate": [
{ "template": "Class A Motorhome PDI", "count": 4, "avgTime": 5.8 },
{ "template": "Class B+ Motorhome PDI", "count": 3, "avgTime": 3.5 },
{ "template": "Travel Trailer PDI", "count": 5, "avgTime": 3.2 },
{ "template": "Fifth Wheel PDI", "count": 2, "avgTime": 4.8 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/service-orders |
List service orders with filters | service-orders:read |
| POST | /api/v1/service-orders |
Create a service order | service-orders:create |
| GET | /api/v1/service-orders/:id |
Get service order details | service-orders:read |
| PATCH | /api/v1/service-orders/:id |
Update service order | service-orders:update |
| PATCH | /api/v1/service-orders/:id/status |
Change service order status | service-orders:update |
| POST | /api/v1/service-orders/:id/lines |
Add a service line item | service-orders:update |
| PATCH | /api/v1/service-orders/:id/lines/:lineId |
Update a service line item | service-orders:update |
| DELETE | /api/v1/service-orders/:id/lines/:lineId |
Remove a service line item | service-orders:update |
| POST | /api/v1/service-orders/:id/invoice |
Generate invoice for service order | service-orders:invoice |
| POST | /api/v1/service-orders/:id/assign-bay |
Assign service order to a bay | service-orders:update |
| POST | /api/v1/service-orders/:id/assign-tech |
Assign technician to service order | service-orders:update |
| GET | /api/v1/service-orders/board |
Get service board view (kanban) | service-orders:read |
| GET | /api/v1/service-orders/stats |
Get service department statistics | service-orders:read |
| GET | /api/v1/service-orders/:id/rect-timeline |
Get RECT timeline for the order | service-orders:read |
Create Service Order Request
POST /api/v1/service-orders
{
"customerId": "cust_01HZ5RVT789",
"vehicleId": "veh_01HZ6WXY456",
"type": "customer_pay",
"priority": "normal",
"promisedDate": "2026-03-01T17:00:00Z",
"concern": "Customer reports water heater not igniting on LP gas. Also requests annual roof seal inspection.",
"lines": [
{
"type": "labor",
"description": "Diagnose water heater LP ignition failure",
"laborHours": 1.5,
"laborRate": 165.00,
"category": "plumbing"
},
{
"type": "labor",
"description": "Annual roof seal inspection and reseal as needed",
"laborHours": 2.0,
"laborRate": 165.00,
"category": "exterior"
}
]
}Service Board Response
GET /api/v1/service-orders/board
{
"columns": [
{
"stage": "waiting_for_parts",
"label": "Waiting for Parts",
"orders": [
{
"id": "so_01HZ8SO001",
"roNumber": "RO-2026-0342",
"vehicle": "2022 Tiffin Allegro 34PA",
"customer": "Rick Johannsen",
"concern": "Slide-out motor replacement",
"daysOpen": 6,
"promisedDate": "2026-02-28T17:00:00Z",
"technicianName": "Carlos Rivera",
"bayNumber": "Bay 3"
}
],
"count": 3
},
{
"stage": "in_progress",
"label": "In Progress",
"orders": [
{
"id": "so_01HZ8SO002",
"roNumber": "RO-2026-0345",
"vehicle": "2024 Grand Design Solitude 390RK",
"customer": "Tom & Linda Chen",
"concern": "AC not cooling, annual maintenance",
"daysOpen": 2,
"promisedDate": "2026-02-25T17:00:00Z",
"technicianName": "Jake Morrison",
"bayNumber": "Bay 1"
}
],
"count": 4
},
{
"stage": "quality_check",
"label": "Quality Check",
"orders": [],
"count": 1
},
{
"stage": "ready_for_pickup",
"label": "Ready for Pickup",
"orders": [],
"count": 2
}
],
"summary": {
"totalOpen": 12,
"overdueCount": 1,
"averageDaysOpen": 4.3
}
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/service-bays |
List all service bays | service-bays:read |
| POST | /api/v1/service-bays |
Create a service bay | service-bays:create |
| GET | /api/v1/service-bays/:id |
Get bay details | service-bays:read |
| PATCH | /api/v1/service-bays/:id |
Update bay information | service-bays:update |
| GET | /api/v1/service-bays/schedule |
Get bay schedule (week view) | service-bays:read |
| POST | /api/v1/service-bays/:id/assign |
Assign a service order to the bay | service-bays:update |
| PATCH | /api/v1/service-bays/:id/release |
Release a bay (mark available) | service-bays:update |
| GET | /api/v1/service-bays/utilization |
Get bay utilization metrics | service-bays:read |
Bay Utilization Response
GET /api/v1/service-bays/utilization?from=2026-02-17&to=2026-02-23
{
"period": { "from": "2026-02-17", "to": "2026-02-23" },
"overallUtilization": 0.72,
"totalBays": 6,
"bays": [
{ "id": "bay_01", "name": "Bay 1 - Full Service", "type": "full_service", "utilizationRate": 0.88, "hoursUsed": 35.2, "ordersCompleted": 4 },
{ "id": "bay_02", "name": "Bay 2 - Full Service", "type": "full_service", "utilizationRate": 0.82, "hoursUsed": 32.8, "ordersCompleted": 3 },
{ "id": "bay_03", "name": "Bay 3 - RV Large", "type": "rv_large", "utilizationRate": 0.75, "hoursUsed": 30.0, "ordersCompleted": 2 },
{ "id": "bay_04", "name": "Bay 4 - RV Large", "type": "rv_large", "utilizationRate": 0.68, "hoursUsed": 27.2, "ordersCompleted": 3 },
{ "id": "bay_05", "name": "Bay 5 - Quick Service", "type": "quick_service", "utilizationRate": 0.65, "hoursUsed": 26.0, "ordersCompleted": 7 },
{ "id": "bay_06", "name": "Bay 6 - Detailing", "type": "detail", "utilizationRate": 0.55, "hoursUsed": 22.0, "ordersCompleted": 6 }
]
}Create Bay Request
POST /api/v1/service-bays
{
"name": "Bay 7 - Outdoor Roof Work",
"type": "outdoor",
"maxLength": 45,
"capabilities": ["roof_repair", "exterior_seal", "awning_service"],
"hourlyRate": 145.00,
"isActive": true
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/technicians |
List all technicians | technicians:read |
| POST | /api/v1/technicians |
Create a technician profile | technicians:create |
| GET | /api/v1/technicians/:id |
Get technician details | technicians:read |
| PATCH | /api/v1/technicians/:id |
Update technician profile | technicians:update |
| GET | /api/v1/technicians/:id/schedule |
Get technician schedule | technicians:read |
| GET | /api/v1/technicians/:id/performance |
Get technician performance metrics | technicians:read |
| GET | /api/v1/technicians/utilization |
Get all technician utilization | technicians:read |
| GET | /api/v1/technicians/availability |
Get technician availability for scheduling | technicians:read |
Technician Performance Response
GET /api/v1/technicians/tech_01HZ8TCH002/performance?from=2026-02-01&to=2026-02-23
{
"technicianId": "tech_01HZ8TCH002",
"name": "Carlos Rivera",
"certifications": ["RVDA Master Certified", "RVIA Level 2", "Onan Generator Specialist"],
"period": { "from": "2026-02-01", "to": "2026-02-23" },
"hoursAvailable": 136.0,
"hoursBilled": 118.5,
"efficiency": 0.871,
"effectiveRate": 1.12,
"ordersCompleted": 14,
"comebacks": 0,
"customerSatisfaction": 4.8,
"revenueGenerated": 19552.50,
"byCategory": [
{ "category": "Electrical", "hours": 32.5, "orders": 4 },
{ "category": "Plumbing", "hours": 24.0, "orders": 3 },
{ "category": "Generator/Solar", "hours": 28.0, "orders": 3 },
{ "category": "Slide-Out Systems", "hours": 18.0, "orders": 2 },
{ "category": "HVAC", "hours": 16.0, "orders": 2 }
]
}Create Technician Request
POST /api/v1/technicians
{
"userId": "usr_01HZ5GNR8T",
"firstName": "Carlos",
"lastName": "Rivera",
"hourlyRate": 165.00,
"certifications": ["RVDA Master Certified", "RVIA Level 2", "Onan Generator Specialist"],
"specialties": ["electrical", "generator", "solar", "slideout_systems"],
"maxHoursPerWeek": 40,
"hireDate": "2021-04-15"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/rect/dashboard |
Get RECT (Repair Event Cycle Time) dashboard | rect:read |
| GET | /api/v1/rect/by-stage |
Get RECT breakdown by stage | rect:read |
| GET | /api/v1/rect/by-type |
Get RECT breakdown by repair type | rect:read |
| GET | /api/v1/rect/:serviceOrderId |
Get RECT timeline for a specific order | rect:read |
RECT Dashboard Response
GET /api/v1/rect/dashboard?from=2026-02-01&to=2026-02-23
{
"averageRECT": 8.4,
"targetRECT": 5.0,
"medianRECT": 6.2,
"totalOrdersClosed": 32,
"ordersOnTarget": 18,
"onTargetRate": 0.5625,
"trend": [
{ "week": "2026-W06", "avgRECT": 9.1, "closed": 7 },
{ "week": "2026-W07", "avgRECT": 8.8, "closed": 9 },
{ "week": "2026-W08", "avgRECT": 7.3, "closed": 8 }
],
"bottlenecks": [
{ "stage": "waiting_for_parts", "avgDays": 3.2, "contribution": 0.38 },
{ "stage": "waiting_for_approval", "avgDays": 1.8, "contribution": 0.21 },
{ "stage": "in_progress", "avgDays": 2.1, "contribution": 0.25 },
{ "stage": "quality_check", "avgDays": 0.5, "contribution": 0.06 },
{ "stage": "other", "avgDays": 0.8, "contribution": 0.10 }
]
}RECT by Service Order Response
GET /api/v1/rect/so_01HZ8SO001
{
"serviceOrderId": "so_01HZ8SO001",
"roNumber": "RO-2026-0342",
"vehicle": "2022 Tiffin Allegro 34PA",
"totalRECT": 6.5,
"target": 5.0,
"onTarget": false,
"timeline": [
{ "stage": "checked_in", "enteredAt": "2026-02-17T08:30:00Z", "duration": 0 },
{ "stage": "waiting_for_diagnosis", "enteredAt": "2026-02-17T08:30:00Z", "duration": 0.25 },
{ "stage": "in_progress", "enteredAt": "2026-02-17T14:30:00Z", "duration": 0.75 },
{ "stage": "waiting_for_parts", "enteredAt": "2026-02-18T14:00:00Z", "duration": 3.0 },
{ "stage": "in_progress", "enteredAt": "2026-02-21T14:00:00Z", "duration": 1.5 },
{ "stage": "quality_check", "enteredAt": "2026-02-23T08:00:00Z", "duration": 0.5 },
{ "stage": "ready_for_pickup", "enteredAt": "2026-02-23T12:00:00Z", "duration": 0.5 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/warranties |
List warranties | warranties:read |
| POST | /api/v1/warranties |
Register a warranty | warranties:create |
| GET | /api/v1/warranties/:id |
Get warranty details | warranties:read |
| PATCH | /api/v1/warranties/:id |
Update warranty information | warranties:update |
| GET | /api/v1/warranties/:id/coverage |
Get detailed coverage breakdown | warranties:read |
| GET | /api/v1/warranties/expiring |
List warranties expiring soon | warranties:read |
Register Warranty Request
POST /api/v1/warranties
{
"vehicleId": "veh_01HZ9VEH001",
"customerId": "cust_01HZ5RVT789",
"type": "manufacturer",
"provider": "Thor Motor Coach",
"policyNumber": "TMC-2026-W-44892",
"coverageType": "comprehensive",
"startDate": "2026-02-28",
"endDate": "2029-02-28",
"mileageLimit": 36000,
"deductible": 0,
"coveredSystems": ["chassis", "engine", "drivetrain", "coach_structural", "appliances", "electrical", "plumbing", "hvac"]
}Expiring Warranties Response
GET /api/v1/warranties/expiring?withinDays=90
{
"data": [
{
"id": "warr_01HZ7W001",
"vehicleId": "veh_01HZ6WXY456",
"vehicle": "2023 Winnebago Navion 24V",
"customer": "Dave Kowalski",
"customerPhone": "+15039876543",
"type": "manufacturer",
"provider": "Winnebago Industries",
"expiresAt": "2026-03-20",
"daysRemaining": 25,
"mileageCurrent": 28450,
"mileageLimit": 36000,
"mileageRemaining": 7550
},
{
"id": "warr_01HZ7W002",
"vehicleId": "veh_01HZ6AAA123",
"vehicle": "2022 Keystone Montana 3761FL",
"customer": "Bill Patterson",
"customerPhone": "+15417778899",
"type": "extended",
"provider": "Good Sam Extended Service Plan",
"expiresAt": "2026-05-15",
"daysRemaining": 81,
"mileageCurrent": null,
"mileageLimit": null,
"mileageRemaining": null
}
],
"meta": { "page": 1, "limit": 25, "total": 7, "totalPages": 1 }
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| POST | /api/v1/warranty-claims |
Create a warranty claim | warranty-claims:create |
| GET | /api/v1/warranty-claims |
List warranty claims | warranty-claims:read |
| GET | /api/v1/warranty-claims/:id |
Get claim details | warranty-claims:read |
| PATCH | /api/v1/warranty-claims/:id |
Update a claim | warranty-claims:update |
| POST | /api/v1/warranty-claims/:id/items |
Add claim line items | warranty-claims:update |
| POST | /api/v1/warranty-claims/:id/submit |
Submit claim to manufacturer | warranty-claims:submit |
| POST | /api/v1/warranty-claims/:id/documents |
Attach supporting documents | warranty-claims:update |
| GET | /api/v1/warranty-claims/stats |
Get warranty claims statistics | warranty-claims:read |
Create Warranty Claim Request
POST /api/v1/warranty-claims
{
"warrantyId": "warr_01HZ7W001",
"serviceOrderId": "so_01HZ8SO003",
"vehicleId": "veh_01HZ6WXY456",
"customerId": "cust_01HZ5RVT789",
"failureDate": "2026-02-20",
"mileageAtFailure": 28450,
"complaint": "Water heater (Truma AquaGo) fails to ignite on LP gas mode. Electric heating element functions normally.",
"cause": "Faulty LP gas solenoid valve - intermittent connection",
"correction": "Replaced LP gas solenoid valve assembly. Tested LP ignition through 10 cycles - all successful.",
"items": [
{
"type": "labor",
"description": "Diagnose and replace LP gas solenoid valve",
"hours": 1.5,
"rate": 145.00,
"amount": 217.50
},
{
"type": "part",
"partNumber": "TRM-70320",
"description": "Truma AquaGo LP Solenoid Valve Assembly",
"quantity": 1,
"unitCost": 87.50,
"amount": 87.50
}
],
"totalClaimed": 305.00
}Warranty Claims Stats Response
GET /api/v1/warranty-claims/stats?from=2026-01-01&to=2026-02-23
{
"totalClaims": 28,
"totalClaimedAmount": 14750.00,
"totalApprovedAmount": 12450.00,
"approvalRate": 0.857,
"averageProcessingDays": 12.3,
"byStatus": [
{ "status": "draft", "count": 2, "amount": 890.00 },
{ "status": "submitted", "count": 5, "amount": 2850.00 },
{ "status": "approved", "count": 18, "amount": 9200.00 },
{ "status": "denied", "count": 2, "amount": 1200.00 },
{ "status": "paid", "count": 6, "amount": 3250.00 }
],
"byManufacturer": [
{ "manufacturer": "Winnebago Industries", "claims": 8, "amount": 4200.00, "approvalRate": 0.875 },
{ "manufacturer": "Thor Motor Coach", "claims": 7, "amount": 3850.00, "approvalRate": 0.857 },
{ "manufacturer": "Grand Design", "claims": 6, "amount": 2900.00, "approvalRate": 0.833 },
{ "manufacturer": "Keystone", "claims": 4, "amount": 2100.00, "approvalRate": 0.750 },
{ "manufacturer": "Tiffin", "claims": 3, "amount": 1700.00, "approvalRate": 1.000 }
],
"topFailureCategories": [
{ "category": "Plumbing/Water Systems", "count": 7 },
{ "category": "Electrical", "count": 6 },
{ "category": "Slide-Out Mechanisms", "count": 4 },
{ "category": "Appliances", "count": 4 },
{ "category": "HVAC", "count": 3 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/parts |
List parts catalog | parts:read |
| POST | /api/v1/parts |
Add a part to catalog | parts:create |
| GET | /api/v1/parts/:id |
Get part details | parts:read |
| PATCH | /api/v1/parts/:id |
Update part information | parts:update |
| GET | /api/v1/parts/inventory |
Get current inventory levels | parts:read |
| POST | /api/v1/parts/orders |
Create a parts purchase order | parts:order |
| GET | /api/v1/parts/orders |
List purchase orders | parts:read |
| GET | /api/v1/parts/orders/:id |
Get purchase order details | parts:read |
| POST | /api/v1/parts/orders/:id/receive |
Receive parts against a PO | parts:receive |
| POST | /api/v1/parts/orders/:id/cancel |
Cancel a purchase order | parts:order |
| GET | /api/v1/parts/low-stock |
List parts below reorder point | parts:read |
| GET | /api/v1/parts/search |
Full-text search parts catalog | parts:read |
| POST | /api/v1/parts/import |
Bulk import parts from CSV | parts:create |
| GET | /api/v1/parts/export |
Export parts inventory | parts:export |
Create Parts Order Request
POST /api/v1/parts/orders
{
"supplierId": "sup_01HZ7NTE001",
"supplierName": "NTP-STAG",
"purchaseOrderNumber": "PO-2026-0089",
"lines": [
{
"partNumber": "TRM-70320",
"description": "Truma AquaGo LP Solenoid Valve Assembly",
"quantity": 3,
"unitCost": 87.50,
"bin": "PLB-C-14"
},
{
"partNumber": "DOM-31093",
"description": "Dometic Penguin II 15K BTU A/C Unit",
"quantity": 1,
"unitCost": 892.00,
"bin": "HVC-A-02"
},
{
"partNumber": "LCI-279258",
"description": "LCI Schwintek Slide Motor Assembly",
"quantity": 2,
"unitCost": 345.00,
"bin": "SLD-B-06"
}
],
"shippingMethod": "ground",
"notes": "Need TRM-70320 ASAP for warranty repair."
}Low Stock Response
GET /api/v1/parts/low-stock
{
"data": [
{
"id": "part_01HZ7PLB001",
"partNumber": "TRM-70320",
"description": "Truma AquaGo LP Solenoid Valve Assembly",
"category": "plumbing",
"currentQty": 0,
"reorderPoint": 2,
"reorderQty": 5,
"unitCost": 87.50,
"lastOrderDate": "2026-01-15",
"supplier": "NTP-STAG",
"bin": "PLB-C-14",
"demandLast90Days": 4
},
{
"id": "part_01HZ7PLB002",
"partNumber": "NORCOLD-634746",
"description": "Norcold Cooling Unit 1210 Series",
"category": "appliances",
"currentQty": 1,
"reorderPoint": 2,
"reorderQty": 3,
"unitCost": 1245.00,
"lastOrderDate": "2025-12-10",
"supplier": "NTP-STAG",
"bin": "APL-A-08",
"demandLast90Days": 2
}
],
"meta": { "page": 1, "limit": 25, "total": 11, "totalPages": 1 }
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| POST | /api/v1/communications/email |
Send an email | communications:send |
| POST | /api/v1/communications/sms |
Send an SMS message | communications:send |
| POST | /api/v1/communications/call |
Log a phone call | communications:send |
| GET | /api/v1/communications/inbox |
Get communication inbox | communications:read |
| GET | /api/v1/communications/customer/:id |
Get all comms for a customer | communications:read |
| GET | /api/v1/communications/threads |
List conversation threads | communications:read |
| GET | /api/v1/communications/threads/:id |
Get thread messages | communications:read |
| POST | /api/v1/communications/webhook/ses |
SES inbound webhook (system) | System |
| POST | /api/v1/communications/webhook/twilio |
Twilio SMS webhook (system) | System |
| POST | /api/v1/communications/webhook/twilio-voice |
Twilio voice webhook (system) | System |
| GET | /api/v1/communications/stats |
Get communication statistics | communications:read |
Send SMS Request
POST /api/v1/communications/sms
{
"customerId": "cust_01HZ5RVT789",
"to": "+15039876543",
"body": "Hi Dave, this is Mike from Sunset RV. Just wanted to let you know the trade-in appraisal for your 2023 Navion came back at $95,000. Want to chat about next steps? Call or text anytime!",
"templateId": null
}Communication Stats Response
GET /api/v1/communications/stats?from=2026-02-01&to=2026-02-23
{
"totalMessages": 847,
"byChannel": {
"email": { "sent": 312, "received": 198, "bounced": 4, "openRate": 0.42 },
"sms": { "sent": 245, "received": 172, "failed": 2, "responseRate": 0.68 },
"phone": { "outbound": 89, "inbound": 64, "missed": 12, "avgDuration": 342 }
},
"responseTime": {
"averageMinutes": 28,
"medianMinutes": 14,
"within1Hour": 0.82,
"within4Hours": 0.95
},
"byUser": [
{ "userId": "usr_01HZ4FKX9Q", "name": "Mike Harrison", "total": 198, "avgResponseMin": 12 },
{ "userId": "usr_01HZ5GNR8T", "name": "Jenny Cole", "total": 172, "avgResponseMin": 18 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/templates |
List message templates | templates:read |
| POST | /api/v1/templates |
Create a message template | templates:create |
| GET | /api/v1/templates/:id |
Get template details | templates:read |
| PATCH | /api/v1/templates/:id |
Update a template | templates:update |
| DELETE | /api/v1/templates/:id |
Delete a template | templates:delete |
| POST | /api/v1/templates/:id/preview |
Preview template with merge data | templates:read |
Create Template Request
POST /api/v1/templates
{
"name": "RV Show Follow-Up",
"channel": "email",
"category": "lead_nurture",
"subject": "Great meeting you at {{show_name}}, {{first_name}}!",
"body": "<p>Hi {{first_name}},</p><p>It was great chatting with you at the {{show_name}}! I hope you enjoyed browsing our lineup of {{interest_type}} units.</p><p>You mentioned interest in the <strong>{{vehicle_of_interest}}</strong>. I wanted to let you know we still have {{available_count}} in stock with show pricing available through {{offer_expiry}}.</p><p>Would you like to schedule a private walk-through at our dealership? I have availability this week and would love to show you the unit in detail.</p><p>Best,<br/>{{salesperson_name}}<br/>{{dealership_name}}<br/>{{salesperson_phone}}</p>",
"mergeFields": ["first_name", "show_name", "interest_type", "vehicle_of_interest", "available_count", "offer_expiry", "salesperson_name", "dealership_name", "salesperson_phone"]
}Template Preview Response
POST /api/v1/templates/tpl_01HZ9TPL001/preview
{
"subject": "Great meeting you at Portland RV & Outdoor Show, Sarah!",
"body": "<p>Hi Sarah,</p><p>It was great chatting with you at the Portland RV & Outdoor Show! I hope you enjoyed browsing our lineup of Class B units.</p><p>You mentioned interest in the <strong>2026 Pleasure-Way Plateau XLTS</strong>. I wanted to let you know we still have 2 in stock with show pricing available through March 15, 2026.</p><p>Would you like to schedule a private walk-through at our dealership? I have availability this week and would love to show you the unit in detail.</p><p>Best,<br/>Mike Harrison<br/>Sunset RV & Marine<br/>(541) 247-1234</p>",
"channel": "email"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/campaigns |
List marketing campaigns | campaigns:read |
| POST | /api/v1/campaigns |
Create a campaign | campaigns:create |
| GET | /api/v1/campaigns/:id |
Get campaign details | campaigns:read |
| PATCH | /api/v1/campaigns/:id |
Update a campaign | campaigns:update |
| DELETE | /api/v1/campaigns/:id |
Delete a campaign | campaigns:delete |
| POST | /api/v1/campaigns/:id/schedule |
Schedule campaign for future send | campaigns:send |
| POST | /api/v1/campaigns/:id/send |
Send campaign immediately | campaigns:send |
| POST | /api/v1/campaigns/:id/cancel |
Cancel a scheduled campaign | campaigns:update |
| GET | /api/v1/campaigns/:id/analytics |
Get campaign performance analytics | campaigns:read |
| GET | /api/v1/campaigns/analytics/summary |
Get cross-campaign analytics summary | campaigns:read |
Create Campaign Request
POST /api/v1/campaigns
{
"name": "Spring Service Special 2026",
"channel": "email",
"templateId": "tpl_01HZ9TPL002",
"audience": {
"type": "segment",
"filters": [
{ "field": "lastServiceDate", "operator": "before", "value": "2025-09-01" },
{ "field": "tags", "operator": "contains", "value": "service_customer" },
{ "field": "status", "operator": "eq", "value": "active" }
]
},
"mergeData": {
"offer_title": "Spring De-Winterization & Safety Check",
"offer_price": "$249",
"regular_price": "$395",
"offer_expiry": "April 30, 2026"
}
}Campaign Analytics Response
GET /api/v1/campaigns/camp_01HZ9CMP001/analytics
{
"campaignId": "camp_01HZ9CMP001",
"name": "Portland RV Show Follow-Up",
"channel": "email",
"sentAt": "2026-02-18T09:00:00Z",
"audience": {
"targeted": 142,
"delivered": 138,
"bounced": 4,
"deliveryRate": 0.972
},
"engagement": {
"opened": 67,
"openRate": 0.486,
"clicked": 28,
"clickRate": 0.203,
"uniqueClicks": 24,
"unsubscribed": 1,
"markedSpam": 0
},
"conversions": {
"appointmentsBooked": 8,
"leadsCreated": 12,
"dealsStarted": 3,
"revenue": 287500.00,
"roi": 14375.0
},
"topLinks": [
{ "url": "https://sunsetrv.com/inventory?type=class_b", "clicks": 14 },
{ "url": "https://sunsetrv.com/schedule-test-drive", "clicks": 8 },
{ "url": "https://sunsetrv.com/show-specials", "clicks": 6 }
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/rv-shows |
List RV shows | rv-shows:read |
| POST | /api/v1/rv-shows |
Create an RV show event | rv-shows:create |
| GET | /api/v1/rv-shows/:id |
Get show details | rv-shows:read |
| PATCH | /api/v1/rv-shows/:id |
Update show details | rv-shows:update |
| DELETE | /api/v1/rv-shows/:id |
Delete an RV show | rv-shows:delete |
| POST | /api/v1/rv-shows/:id/inventory |
Add vehicle to show inventory | rv-shows:update |
| DELETE | /api/v1/rv-shows/:id/inventory/:vehicleId |
Remove vehicle from show | rv-shows:update |
| POST | /api/v1/rv-shows/:id/leads |
Add a lead captured at the show | rv-shows:update |
| GET | /api/v1/rv-shows/:id/leads |
List leads from the show | rv-shows:read |
| GET | /api/v1/rv-shows/:id/analytics |
Get show performance analytics | rv-shows:read |
| POST | /api/v1/rv-shows/:id/follow-up-all |
Trigger follow-up for all show leads | rv-shows:update |
| PATCH | /api/v1/rv-shows/:id/status |
Update show status | rv-shows:update |
| GET | /api/v1/rv-shows/upcoming |
List upcoming shows | rv-shows:read |
Create RV Show Request
POST /api/v1/rv-shows
{
"name": "Portland RV & Outdoor Show 2026",
"venue": "Portland Expo Center",
"address": {
"street": "2060 N Marine Dr",
"city": "Portland",
"state": "OR",
"zip": "97217"
},
"startDate": "2026-02-13",
"endDate": "2026-02-16",
"boothNumber": "A-142",
"boothSize": "40x60",
"budget": 12500.00,
"staffIds": ["usr_01HZ4FKX9Q", "usr_01HZ5GNR8T"],
"goals": {
"leadsTarget": 100,
"appointmentsTarget": 25,
"salesTarget": 5
}
}Show Analytics Response
GET /api/v1/rv-shows/show_01HZ7RVS001/analytics
{
"showId": "show_01HZ7RVS001",
"name": "Portland RV & Outdoor Show 2026",
"status": "completed",
"investment": {
"boothFee": 8500.00,
"staffCosts": 2400.00,
"marketing": 1200.00,
"transportation": 850.00,
"totalInvestment": 12950.00
},
"leads": {
"total": 142,
"qualified": 68,
"contacted": 98,
"appointmentsSet": 22,
"contactRate": 0.690,
"qualificationRate": 0.479
},
"sales": {
"dealsClosed": 4,
"dealsInProgress": 7,
"totalRevenue": 487500.00,
"totalGrossProfit": 72800.00,
"costPerLead": 91.20,
"costPerSale": 3237.50,
"roi": 4.62
},
"byInterest": [
{ "type": "Class A", "leads": 28, "sales": 1 },
{ "type": "Class B/B+", "leads": 34, "sales": 1 },
{ "type": "Class C", "leads": 18, "sales": 0 },
{ "type": "Travel Trailer", "leads": 32, "sales": 1 },
{ "type": "Fifth Wheel", "leads": 22, "sales": 1 },
{ "type": "Toy Hauler", "leads": 8, "sales": 0 }
],
"followUpStatus": {
"emailsSent": 138,
"smsSent": 89,
"callsMade": 68,
"notContacted": 6
}
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| POST | /api/v1/ai/chat |
Interactive AI chat assistant (streaming) | ai:chat |
| POST | /api/v1/ai/generate-description |
Generate vehicle listing description | ai:use |
| POST | /api/v1/ai/draft-response |
Draft customer communication response | ai:use |
| POST | /api/v1/ai/analyze-sentiment |
Analyze customer sentiment | ai:use |
| POST | /api/v1/ai/score-lead |
AI-powered lead scoring | ai:use |
| GET | /api/v1/ai/insights/:entityType/:id |
Get AI insights for an entity | ai:use |
| GET | /api/v1/ai/usage |
Get AI usage and token stats | ai:read |
Chat Request (Streaming)
POST /api/v1/ai/chat
{
"message": "What are the top 5 leads most likely to close this week based on recent activity?",
"context": "sales_pipeline",
"stream": true
}Chat Response (Server-Sent Events)
HTTP/1.1 200 OK
Content-Type: text/event-stream
data: {"type":"start","messageId":"msg_01HZ9AI001"}
data: {"type":"chunk","content":"Based on recent activity patterns, here are your "}
data: {"type":"chunk","content":"top 5 leads most likely to close this week:\n\n"}
data: {"type":"chunk","content":"1. **Dave Kowalski** (View 24V) - 92% probability\n"}
data: {"type":"chunk","content":" - Trade appraisal completed, financing pre-approved\n"}
data: {"type":"chunk","content":" - Test drive scheduled for Tuesday\n\n"}
data: {"type":"chunk","content":"2. **Sarah Mitchell** (Plateau XLTS) - 78% probability\n"}
data: {"type":"chunk","content":" - Opened follow-up email 4 times, clicked pricing link\n"}
data: {"type":"chunk","content":" - Responded to SMS within 3 minutes\n\n"}
data: {"type":"chunk","content":"3. **Tom Chen** (Solitude 390RK) - 74% probability\n"}
data: {"type":"chunk","content":" - Second visit to dealership, brought spouse\n"}
data: {"type":"chunk","content":" - Asked about extended warranty options\n\n"}
data: {"type":"chunk","content":"4. **Rick Johannsen** (Allegro 34PA) - 71% probability\n"}
data: {"type":"chunk","content":" - Cash buyer, no financing contingency\n"}
data: {"type":"chunk","content":" - Currently in service - upgrade opportunity\n\n"}
data: {"type":"chunk","content":"5. **Linda Park** (Montana 3761FL) - 68% probability\n"}
data: {"type":"chunk","content":" - Submitted credit application yesterday\n"}
data: {"type":"chunk","content":" - Moving to full-time RV lifestyle (motivated)\n"}
data: {"type":"end","tokensUsed":342,"messageId":"msg_01HZ9AI001"}
Generate Vehicle Description Request
POST /api/v1/ai/generate-description
{
"vehicleId": "veh_01HZ9VEH001",
"tone": "professional_enthusiastic",
"platform": "website",
"includeFeatures": true,
"maxLength": 500
}Generate Vehicle Description Response
{
"vehicleId": "veh_01HZ9VEH001",
"description": "Adventure meets luxury in this brand-new 2026 Thor Gemini 23TW AWD. Built on the Ford Transit 350 AWD chassis with a powerful 2.0L EcoBoost engine and 10-speed automatic transmission, this Class B+ delivers confident handling on any terrain.\n\nInside, the thoughtfully designed floorplan features a convertible Murphy bed, full galley kitchen, and a surprisingly spacious wet bath. The Onan 4.0kW generator and solar panel prep keep you powered off-grid, while the 15K BTU A/C and tankless water heater ensure comfort in any climate.\n\nAt just 24'2\", the Gemini 23TW is nimble enough for everyday driving yet sleeps 4 comfortably. Finished in Silver Spruce with the Coastal Gray interior, this coach is ready for mountain passes, desert highways, and everything in between.\n\nStop by Sunset RV & Marine for a walk-through today. Show-season pricing won't last!",
"tokensUsed": 218,
"platform": "website"
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/reports |
List saved reports | reports:read |
| POST | /api/v1/reports |
Create a custom report definition | reports:create |
| GET | /api/v1/reports/:id |
Get report definition | reports:read |
| POST | /api/v1/reports/:id/run |
Execute a report and return results | reports:run |
| DELETE | /api/v1/reports/:id |
Delete a saved report | reports:delete |
| GET | /api/v1/reports/templates |
List report templates | reports:read |
| POST | /api/v1/reports/:id/schedule |
Schedule recurring report execution | reports:schedule |
| GET | /api/v1/reports/:id/export/:format |
Export report as PDF, CSV, or XLSX | reports:export |
| GET | /api/v1/reports/pre-built/:type |
Run a pre-built report by type | reports:run |
Create Report Request
POST /api/v1/reports
{
"name": "Monthly Gross Profit by Salesperson",
"description": "Breaks down front-end and back-end gross profit per salesperson for the month",
"type": "sales",
"dataSource": "deals",
"columns": [
{ "field": "salesPersonName", "label": "Salesperson" },
{ "field": "dealCount", "label": "Units Sold", "aggregate": "count" },
{ "field": "frontEndGross", "label": "Front Gross", "aggregate": "sum", "format": "currency" },
{ "field": "backEndGross", "label": "Back Gross", "aggregate": "sum", "format": "currency" },
{ "field": "totalGross", "label": "Total Gross", "aggregate": "sum", "format": "currency" },
{ "field": "averageGross", "label": "Avg/Deal", "aggregate": "avg", "format": "currency" }
],
"filters": [
{ "field": "status", "operator": "in", "value": ["delivered", "funded"] },
{ "field": "closedAt", "operator": "within", "value": "current_month" }
],
"groupBy": "salesPersonId",
"sortBy": { "field": "totalGross", "direction": "desc" }
}Pre-Built Report Response
GET /api/v1/reports/pre-built/inventory-aging?asOf=2026-02-23
{
"report": "Inventory Aging Report",
"generatedAt": "2026-02-23T15:00:00Z",
"summary": {
"totalUnits": 87,
"totalValue": 7845000.00,
"averageAge": 52,
"unitsOver90Days": 12
},
"data": [
{
"bucket": "0-30 days",
"new": { "count": 18, "value": 2340000.00 },
"used": { "count": 8, "value": 420000.00 },
"total": { "count": 26, "value": 2760000.00 }
},
{
"bucket": "31-60 days",
"new": { "count": 14, "value": 1680000.00 },
"used": { "count": 10, "value": 575000.00 },
"total": { "count": 24, "value": 2255000.00 }
},
{
"bucket": "61-90 days",
"new": { "count": 12, "value": 1560000.00 },
"used": { "count": 13, "value": 645000.00 },
"total": { "count": 25, "value": 2205000.00 }
},
{
"bucket": "90-120 days",
"new": { "count": 4, "value": 380000.00 },
"used": { "count": 3, "value": 112000.00 },
"total": { "count": 7, "value": 492000.00 }
},
{
"bucket": "120+ days",
"new": { "count": 2, "value": 85000.00 },
"used": { "count": 3, "value": 48000.00 },
"total": { "count": 5, "value": 133000.00 }
}
]
}| Method | Path | Description | Required Permission |
|---|---|---|---|
| GET | /api/v1/dashboards |
List dashboards | dashboards:read |
| POST | /api/v1/dashboards |
Create a custom dashboard | dashboards:create |
| GET | /api/v1/dashboards/:id |
Get dashboard with widget data | dashboards:read |
| PATCH | /api/v1/dashboards/:id |
Update dashboard layout/settings | dashboards:update |
| DELETE | /api/v1/dashboards/:id |
Delete a dashboard | dashboards:delete |
| POST | /api/v1/dashboards/:id/widgets |
Add a widget to a dashboard | dashboards:update |
| PATCH | /api/v1/dashboards/:id/widgets/:wid |
Update a widget configuration | dashboards:update |
| DELETE | /api/v1/dashboards/:id/widgets/:wid |
Remove a widget from a dashboard | dashboards:update |
| POST | /api/v1/dashboards/:id/clone |
Clone an existing dashboard | dashboards:create |
| GET | /api/v1/dashboards/default |
Get the default dashboard for current user's role | dashboards:read |
Create Dashboard Request
POST /api/v1/dashboards
{
"name": "Sales Manager Command Center",
"description": "Real-time view of sales pipeline, inventory, and team performance",
"isDefault": false,
"layout": "grid",
"refreshInterval": 300,
"widgets": [
{
"type": "metric_card",
"title": "MTD Gross Profit",
"position": { "x": 0, "y": 0, "w": 3, "h": 1 },
"config": { "dataSource": "deals", "metric": "totalGross", "period": "current_month", "compareWith": "previous_month" }
},
{
"type": "metric_card",
"title": "Units Sold MTD",
"position": { "x": 3, "y": 0, "w": 3, "h": 1 },
"config": { "dataSource": "deals", "metric": "count", "period": "current_month", "compareWith": "previous_month" }
},
{
"type": "metric_card",
"title": "Active Leads",
"position": { "x": 6, "y": 0, "w": 3, "h": 1 },
"config": { "dataSource": "leads", "metric": "count", "filter": { "status": "active" } }
},
{
"type": "chart_bar",
"title": "Sales by Salesperson",
"position": { "x": 0, "y": 1, "w": 6, "h": 2 },
"config": { "dataSource": "deals", "metric": "totalGross", "groupBy": "salesPersonId", "period": "current_month" }
},
{
"type": "chart_funnel",
"title": "Lead Pipeline",
"position": { "x": 6, "y": 1, "w": 6, "h": 2 },
"config": { "dataSource": "leads", "stages": ["new", "contacted", "qualified", "demo_scheduled", "proposal", "negotiation", "won"] }
},
{
"type": "table",
"title": "Hot Leads (Score > 80)",
"position": { "x": 0, "y": 3, "w": 12, "h": 2 },
"config": { "dataSource": "leads", "filter": { "aiScore.gte": 80 }, "columns": ["customerName", "interest", "score", "lastActivity", "assignedTo"], "limit": 10 }
}
]
}Default Dashboard Response
GET /api/v1/dashboards/default
{
"id": "dash_01HZ9DSH001",
"name": "Sales Manager Command Center",
"role": "sales_manager",
"lastUpdated": "2026-02-23T15:05:00Z",
"widgets": [
{
"id": "wgt_001",
"type": "metric_card",
"title": "MTD Gross Profit",
"data": {
"value": 187450.00,
"previousValue": 162300.00,
"change": 0.155,
"trend": "up"
}
},
{
"id": "wgt_002",
"type": "metric_card",
"title": "Units Sold MTD",
"data": {
"value": 11,
"previousValue": 9,
"change": 0.222,
"trend": "up"
}
},
{
"id": "wgt_003",
"type": "metric_card",
"title": "Active Leads",
"data": {
"value": 86,
"previousValue": 72,
"change": 0.194,
"trend": "up"
}
},
{
"id": "wgt_004",
"type": "chart_bar",
"title": "Sales by Salesperson",
"data": {
"labels": ["Mike Harrison", "Jenny Cole", "Tom Bradley", "Kim Nguyen"],
"series": [
{ "name": "Front Gross", "values": [48200, 38500, 32100, 28400] },
{ "name": "Back Gross", "values": [12800, 10200, 8900, 8350] }
]
}
},
{
"id": "wgt_005",
"type": "chart_funnel",
"title": "Lead Pipeline",
"data": {
"stages": [
{ "name": "New", "value": 42, "conversionRate": null },
{ "name": "Contacted", "value": 31, "conversionRate": 0.738 },
{ "name": "Qualified", "value": 28, "conversionRate": 0.903 },
{ "name": "Demo Scheduled", "value": 15, "conversionRate": 0.536 },
{ "name": "Proposal", "value": 12, "conversionRate": 0.800 },
{ "name": "Negotiation", "value": 8, "conversionRate": 0.667 },
{ "name": "Won", "value": 27, "conversionRate": null }
]
}
},
{
"id": "wgt_006",
"type": "table",
"title": "Hot Leads (Score > 80)",
"data": {
"rows": [
{ "customerName": "Dave Kowalski", "interest": "2026 Winnebago View 24V", "score": 92, "lastActivity": "2h ago", "assignedTo": "Mike Harrison" },
{ "customerName": "Sarah Mitchell", "interest": "2026 Pleasure-Way Plateau XLTS", "score": 85, "lastActivity": "4h ago", "assignedTo": "Mike Harrison" },
{ "customerName": "Tom Chen", "interest": "2025 Grand Design Solitude 390RK", "score": 83, "lastActivity": "1d ago", "assignedTo": "Jenny Cole" },
{ "customerName": "Rick Johannsen", "interest": "2024 Tiffin Allegro 34PA", "score": 81, "lastActivity": "3h ago", "assignedTo": "Tom Bradley" }
]
}
}
]
}| Code | Meaning |
|---|---|
200 |
Success |
201 |
Created |
204 |
No Content (successful DELETE) |
400 |
Bad Request (validation error) |
401 |
Unauthorized (missing/invalid token) |
403 |
Forbidden (insufficient permissions) |
404 |
Not Found |
409 |
Conflict (duplicate, optimistic lock) |
422 |
Unprocessable Entity (business rule violation) |
429 |
Too Many Requests (rate limited) |
500 |
Internal Server Error |
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"details": [
{ "field": "email", "message": "must be a valid email address" },
{ "field": "phone", "message": "must match E.164 format" }
],
"requestId": "req_01HZ9ERR001",
"timestamp": "2026-02-23T15:30:00Z"
}
}All paginated endpoints return:
{
"data": [ ... ],
"meta": {
"page": 1,
"limit": 25,
"total": 142,
"totalPages": 6
}
}Query parameters: ?page=1&limit=25&sort=createdAt&order=desc
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /activity |
Paginated activity feed | JWT |
| GET | /activity/stats |
Staff efficiency metrics (7d) | JWT |
Query params (GET /activity): ?user_id=, ?action=, ?entity_type=, ?cursor=, ?limit=
Query params (GET /activity/stats): ?days=7
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /floor-plan-audits |
Start new audit (snapshots units) | JWT |
| GET | /floor-plan-audits |
List audits | JWT |
| GET | /floor-plan-audits/:id |
Get audit with items + unit detail | JWT |
| PATCH | /floor-plan-audits/:id/items/:itemId |
Verify/mark unit | JWT |
| POST | /floor-plan-audits/:id/complete |
Finalize audit | JWT |
Request body (POST /floor-plan-audits):
{ "lot_id": "uuid (optional)", "notes": "string (optional)" }Request body (PATCH ...items/:itemId):
{ "status": "verified|missing|mislocated", "found_zone": "string", "notes": "string" }| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /service-bays |
List bays with assignments | JWT |
| POST | /service-bays |
Create bay | JWT |
| PATCH | /service-bays/:id |
Update bay | JWT |
| DELETE | /service-bays/:id |
Delete bay (must be unoccupied) | JWT |
| POST | /service-bays/:id/check-in |
Assign unit to bay | JWT |
| PATCH | /service-bays/:id/stage |
Advance service stage | JWT |
| POST | /service-bays/:id/check-out |
Release bay | JWT |
| GET | /service-bays/metrics |
Bay utilization and throughput | JWT |
Stage transitions: checked_in → diagnosis → in_repair → quality_check → ready
Request body (POST .../check-in):
{
"unit_id": "uuid",
"work_order_id": "uuid (optional)",
"technician_id": "uuid (optional)",
"notes": "string (optional)"
}| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /dashboard-config |
Get user's widget layout | JWT |
| PUT | /dashboard-config |
Save widget layout | JWT |
| POST | /dashboard-config/reset |
Reset to default layout | JWT |
Request body (PUT /dashboard-config):
{
"layout": [
{ "widget_id": "inventory_summary", "x": 0, "y": 0, "w": 2, "h": 1 },
{ "widget_id": "tracker_health", "x": 2, "y": 0, "w": 1, "h": 1 }
]
}Available widget IDs: inventory_summary, tracker_health, alert_feed, aging_chart, lot_utilization, recent_activity, unit_status_breakdown, quick_actions
// Request
{
"email": "manager@example.com",
"password": "SecureP@ss123"
}
// Response 200
{
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "manager@example.com",
"name": "Jane Smith",
"role": "manager",
"dealership_id": "d1234567-89ab-cdef-0123-456789abcdef"
}
}
}
// Response 401
{
"error": "Invalid email or password",
"status_code": 401
}// Request
{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
// Response 200
{
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}
}GET /api/v1/units?status=available&limit=20&cursor=abc123
Authorization: Bearer <token>
// Response 200
{
"data": [
{
"id": "u-550e8400-e29b-41d4-a716-446655440000",
"stock_number": "RV-2025-001",
"vin": "1UJBJ0BS7L1AB1234",
"year": 2025,
"make": "Jayco",
"model": "Eagle HT 28.5RSTS",
"unit_type": "travel_trailer",
"status": "available",
"current_zone": "A",
"current_row": "3",
"current_spot": 12,
"msrp": "45999.00",
"arrived_at": "2025-12-15T10:30:00Z",
"last_moved_at": "2026-01-20T14:22:00Z",
"created_at": "2025-12-15T10:30:00Z"
}
],
"pagination": {
"cursor": "def456",
"has_more": true
}
}// Request
{
"stock_number": "RV-2025-042",
"vin": "1UJBJ0BS7L1AB5678",
"year": 2025,
"make": "Winnebago",
"model": "View 24D",
"unit_type": "class_c",
"msrp": "142500.00",
"lot_id": "lot-123"
}
// Response 201
{
"data": {
"id": "u-660e8400-e29b-41d4-a716-446655440001",
"stock_number": "RV-2025-042",
"status": "new_arrival",
"created_at": "2026-04-03T15:00:00Z"
}
}GET /api/v1/trackers
Authorization: Bearer <token>
// Response 200
{
"data": [
{
"id": "t-001",
"device_eui": "A84041FFFF1E4B2C",
"status": "assigned",
"battery_pct": 87,
"unit_id": "u-550e8400-e29b-41d4-a716-446655440000",
"last_seen_at": "2026-04-03T14:55:00Z",
"firmware_version": "1.2.3"
}
]
}GET /api/v1/alerts?severity=high&acknowledged=false
Authorization: Bearer <token>
// Response 200
{
"data": [
{
"id": "alert-001",
"alert_type": "geofence_exit",
"severity": "high",
"message": "Unit RV-2025-001 exited lot boundary",
"unit_id": "u-550e8400-e29b-41d4-a716-446655440000",
"acknowledged": false,
"created_at": "2026-04-03T02:15:00Z"
}
]
}// Request
{
"unit_id": "u-550e8400-e29b-41d4-a716-446655440000",
"order_type": "pdi",
"priority": "high",
"description": "Pre-delivery inspection for unit RV-2025-001",
"assigned_to": "user-tech-001"
}
// Response 201
{
"data": {
"id": "wo-001",
"unit_id": "u-550e8400-e29b-41d4-a716-446655440000",
"order_type": "pdi",
"priority": "high",
"status": "open",
"created_at": "2026-04-03T15:30:00Z"
}
}GET /api/v1/analytics/inventory
Authorization: Bearer <token>
// Response 200
{
"data": {
"total_units": 247,
"by_status": {
"available": 182,
"sold": 31,
"in_service": 18,
"new_arrival": 12,
"delivered": 4
},
"by_type": {
"travel_trailer": 98,
"fifth_wheel": 67,
"class_a": 42,
"class_c": 28,
"toy_hauler": 12
},
"average_days_on_lot": 45.2,
"total_msrp_value": "12450000.00"
}
}// 1. Client sends auth message
{ "type": "auth", "token": "eyJhbGciOiJIUzI1NiIs..." }
// 2. Server responds with connected
{ "type": "connected", "dealership_id": "d1234567-..." }
// 3. Server pushes location updates
{
"type": "location_update",
"unit_id": "u-550e8400-...",
"latitude": 27.9506,
"longitude": -82.4572,
"zone": "A",
"row": "3",
"spot": 12,
"timestamp": "2026-04-03T14:55:00Z"
}
// 4. Server sends heartbeat pings
{ "type": "ping" }
// 5. Client responds with pong
{ "type": "pong" }