Migration Guide

This guide is meant for API users migrating from version 1 to version 2 of the REST API. Note that the emphasis of this guide is on the breaking changes and functionality changes between version 1 and 2, not the newly supported rental vehicle service requests. Do check the changelog for any new additional features as well.

Pathing Changes

Prefixing

For version 2 all paths have been prefixed with /v2. For example, fetching a contract in version 1 is through GET /contracts/{licensePlate} and in version 2 this is GET /v2/contracts/{licensePlate}. All paths in version 1 have been ported over to version 2.

Reason for not invoicing

Setting the reason for not invoicing through ROB-Net was done through PUT /servicerequests/{id}/invoices. This has been moved to POST /v2/servicerequests/{id}/invoices/status for the following reasons:

  • Using the HTTP POST method signifies that setting the status is a one time action
  • The new path segment clearly separates it from other methods, such as the ones for fetching and creating new invoices

Mapping version 1 to version 2

The mapping below shows all the version 1 paths and their version 2 equivalents.

Version 1 Version 2
/contracts/{licensePlate} /v2/contracts/{licensePlate}
/contracts/{licensePlate}/components /v2/contracts/{licensePlate}/components
/servicerequests/{id}/invoices /v2/servicerequests/{id}/invoices
/servicerequests/{id}/invoices/{invoiceId} /v2/servicerequests/{id}/invoices/{invoiceId}
/servicerequests/{id}/invoicetemplate /v2/servicerequests/{id}/invoicetemplate
/servicerequests/{id}/invoices/{invoiceId}/pdf /v2/servicerequests/{id}/invoices/{invoiceId}/pdf
/lessors /v2/lessors
/lessors/{lessorId}/contracts/{licensePlate} /v2/lessors/{lessorId}/contracts/{licensePlate}
/lessors/{lessorId}/contracts/{licensePlate}/components /v2/lessors/{lessorId}/contracts/{licensePlate}/components
/requests /v2/requests
/servicerequests/{id} /v2/servicerequests/{id}
/servicerequests /v2/servicerequests
/servicerequests/{requestId}/components/{componentId} /v2/servicerequests/{requestId}/components/{componentId}
/servicerequests/{requestId}/components/{componentId}/cancel /v2/servicerequests/{requestId}/components/{componentId}/cancel
/tire /v2/tire
/tires /v2/tires
/tires/makes /v2/tires/makes

New methods

Version 2 includes several new methods:

SLA Support

A big change in this new version of the API is the introduction of Service Level Agreement(s) (SLA). Users can now configure default prices for repair and maintenance and tires activities but also configure prices for specific lessors and optionally one or more dealerships, which are determined by the object a service request is made for. Some prices can even be tied to a specific object type category. This allows setting a different price for a truck and a normal passenger car respectively for instance.

The methods listed below are now enriched when an applicable SLA exists. More details can be found in the introduction or you can dive straight into the technicalities with the API v2 details.

  • GET /v2/contracts/{licensePlate}
  • GET /v2/contracts/{licensePlate}/components
  • GET /v2/lessors/{lessorId}/contracts/{licensePlate}
  • GET /v2/lessors/{lessorId}/contracts/{licensePlate}/components

Request Model Changes

Service Request

Appointment Field

With the introduction of rental vehicle lines it is now possible to have different appointment date types:

Workshop date
the date the object is brought to the workshop for repair, maintenance and/or tire related activities
Checkout date
the date and time the rental vehicle for the object is provided to the lessee

See the difference below for an example how the appointment field usage has changed for repair and maintenance and/or tires service request.


 {
-  "date": "2021-06-16T00:00:00Z",
+  "workshopDate": "2021-06-16",
   "workOrderNumber": "werkbon-12",
   "contact": {
     "name": "Piet van Putten",
     "phone": "+316543210"
   },
   "estimatedDurationInDays": 3
 }
            
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

Components Field

The notion of subcomponents has been further integrated into the API by introducing a different schema (type) for it. This means that the service request lines have different schemas for themselves and their respective children. Lines are now components and their subcomponents are subcomponents.

This has the benefit of the specification containing better constraints for each type, for example the subcomponents do not always require an operation code and reason code, unlike components (Lines) that always do require those.

To express the type change the field components has been renamed to subcomponent. The difference below illustrates this. The components field name is still used when referring to lines, for example when using the service request creation and mutation methods or the line mutation methods.


 "components": [
  {
    "id": "72870000-d0c3-9eb6-2e46-08d937174b75",
    "rob": {
      "code": "3198"
    },
-   "components": [
+   "subcomponents": [
      {
        "id": "84a3f5db-1aa7-4f71-aca1-34cc66b71c71",
        "rob": {
          "code": "3101"
        },
-       "components": [
+       "subcomponents": [
        ...
            
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Part Field

The component part field's discriminator field componentPartType has been renamed to partType. See the difference below for an example.

As well as the discriminator field rename, the actual content of the part field no longer allows the submission of the abstract base part. The base part was an empty JSON object containing the value Base as the discriminator value. Submitting the base part is silently ignored by the v1 API. The v2 API actively rejects requests containing the base part.


 {
   "rob": {
     "code": "3101"
   },
   "operation": {
     "code": "08"
   },
   "components": [],
   "value": 6.1,
   "part": {
-    "componentPartType": "Tire",
+    "partType": "Tire",
     "id": 1373929
   }
 },
            
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Supplier ID Field

The field supplierId was required to always be the ID of the authorized supplier during service request creation. With other words this field has static content for each user thus the field has been deleted as it serves no real purpose.


 {
-  "version": "2019-08-01",
-  "revision": 1,
   "status": "Draft",
-  "supplierId": 307247,
   "appointment": {
   ...
            
  • POST /v2/servicerequests

Version and Revision Fields

The fields version and revision served no real purpose and have been removed.


 {
-  "version": "2019-08-01",
-  "revision": 1,
   "status": "Draft",
-  "supplierId": 307247,
   "appointment": {
   ...
            
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Value Field

The field value has changed type from number to string in both service request lines and subcomponents. Numbers are expected to be in decimal notation with the dot character (.) as decimal separator and no thousands separator. As an example of correct formatting the difference below shows an hours reading component of 1,500.50 hours.


 {
   "rob": {
     "code": "5449"
   },
   "operation": {
     "code": "19"
   },
   "reason": {
     "code": "99"
   },
-  "value": 1500.5
+  "value": "1500.5"
 }
            
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Tires

Makecode Parameter

The parameter makeCode may now appear multiple times while searching for tires. So it is now possible to search for multiple tiremake codes at once


- /v2/tires?makeCode=CO
+ /v2/tires?makeCode=CO&makeCode=MI
            
  • GET /v2/tires

SeasonIndicator Parameter

The parameter seasonIndicators has been renamed to seasonindicators


- /v2/tires?seasonIndicators=Summer&seasonIndicators=Winter
+ /v2/tires?seasonIndicator=Summer&seasonIndicator=Winter
            
  • GET /v2/tires

Response Model Changes

Allowed Components

Price Type Field

The priceType field in the allowed components response of the API has been removed as it always contained the value "Total".


 {
   "components": [
     {
       "description": "Bandbewerkingen",
       "robCode": "3197",
       "operation": {
         "types": [],
         "code": "00",
         "description": "Uitvoeren"
       },
       "reasons": [
         {
           "code": "99",
           "description": "n.v.t."
         }
       ],
       "requiredFields": [
         "RobCode",
         "Operation",
         "Reason",
         "Price"
       ],
       "optionalFields": [],
       "locations": [],
-      "priceType": "Total",
       "subcomponents": []
     }
   ]
 }
            
  • GET /v2/components
  • GET /v2/contracts/{licensePlate}/components
  • GET /v2/lessors/{lessorId}/contracts/{licensePlate}/components

Service Level Field

The optional field serviceLevel has been added to the allowed components output. This field contains the configured price from the applicable service level for the given object for easy access.


 {
   "description": "Disposal fee",
   "robCode": "3156",
   "requiredFields": [
       "RobCode",
       "Price"
   ],
   "optionalFields": [],
+  "serviceLevel": {
+      "price": 2.00
+  },
   "subcomponents": []
 }
            
  • GET /v2/contracts/{licensePlate}/components
  • GET /v2/lessors/{lessorId}/contracts/{licensePlate}/components

Types Field

For consistency in the allowed components response model the array field types has been removed. Instead, the operation type code associated with the line component is modelled the same way as in the subcomponents.

No operation type codes are in use for lines thus this change has no impact. Nonetheless, a fictional component response is included in the difference below.


 {
   "components": [
     {
       "description": "Bandbewerkingen",
       "robCode": "3197",
       "operation": {
-        "types": [
-          {
-            "code": "01",
-            "description": "Nieuw"
-          }
-        ],
+        "type": {
+          "code": "01",
+          "description": "Nieuw"
+        },
         "code": "00",
         "description": "Uitvoeren"
       },
       "reasons": [
         {
           "code": "99",
           "description": "n.v.t."
         }
       ],
       "requiredFields": [
         "RobCode",
         "Operation",
         "Reason",
         "Price"
       ],
       "optionalFields": [],
       "locations": [],
       "priceType": "Total",
       "subcomponents": []
     }
   ]
 }
            
  • GET /v2/components
  • GET /v2/contracts/{licensePlate}/components
  • GET /v2/lessors/{lessorId}/contracts/{licensePlate}/components

Cancel Line

Cancelling a service request line through PUT /v2/servicerequests/{id}/components/{componentId} now returns the cancelled line in the response.


{
  "component": {
    "id": "72870000-d0c3-9eb6-2e46-08d937174b75",
    "rob": {
      "code": "3198",
      "description": "Bandvervanging"
    },
    "supplierCode": "",
    "operation": {
      "code": "00",
      "description": "Uitvoeren"
    },
    "reason": {
      "code": "99",
      "description": "n.v.t."
    },
    "price": 102.00,
    "status": {
      "code": "Cancelled",
      "description": "Vervallen"
    },
    "subcomponents": [
      ...
    ]
  }
}
            
  • POST /v2/servicerequests/{id}/components/{componentId}/cancel

Contract

The contract in the previous REST API version had no clear distinction between agreements pertaining to the lessor and lessee and requirements/constraints meant for the supplier specifically. This has been addressed and a clear separation has been introduced:

  • A leaseContract containing the agreements between lessor and lessee
  • A supplierContract containing the requirements and constraints as setup by the lessor for the lessee in ROB-Net. The contract directly affects what is allowed to be submitted in a service request.

The settings for repair and maintenance, tires and rental vehicle have been more clearly separated in both fields mentioned above. See the mapping and difference below for more details. The mapping will show where the information from the previous REST API version has ended up in version 2.

Unchanged fields have been omitted from this mapping for brevity.

Version 1 Version 2 Remark
vehicle.make vehicle.vehicleMake Renamed
vehicle.model vehicle.vehicleModel Renamed
vehicle.type vehicle.vehicleType Renamed
vehicle.objectType.objectTypeCategory New mandatory field used to match the applicable service level rate(s)
vehicle.dealership New optional field with information about the dealership asociated with the lessor object determined by its vehicle make
vehicle.currentTireSeasonCode Removed. Please see the existing field vehicle.mountedTires
vehicle.currentTireCategoryCode Removed. Please see the existing field vehicle.mountedTires
endDate leaseContract.endDate Moved
maximumMileage leaseContract.maximumMileage Moved
leaseContract.repairAndMaintenance New field with parameters for repair and maintenance activities that are part of the contract between lessor and lessee
leaseContract.repairAndMaintenance.inContract New field that indicates if repair and maintenance is part of the contract between lessor and lessee
information leaseContract.repairAndMaintenance.remark Moved
leaseContract.repairAndMaintenance.inContract New field that indicates if repair and maintenance activities are part of the contract between lessor and lessee
leaseContract.tires New field with parameters for tire activities that are part of the contract between lessor and lessee
leaseContract.tires.inContract New field that indicates if tire activities are part of the contract between lessor and lessee
leaseContract.tires.tireSwapInContract New field that indicates if swapping tires is part of the contract between lessor and lessee
leaseContract.tires.rofTiresInContract New field that indicates if employing Run On Flat (ROF) tires is part of the contract between lessor and lessee
leaseContract.tires.allSeasonTiresInContract New field that indicates if employing all season tires is part of the contract between lessor and lessee
leaseContract.tires.nitrogenTireFillingInContract New field that indicates if filling tires with nitrogen is part of the contract between lessor and lessee
leaseContract.tires.usedTiresInContract New field that indicates purchase of used tires is part of the contract between lessor and lessee
winterTireSetAlreadyPurchased leaseContract.tires.hasTireSetForTireSwapInStorage Moved
leaseContract.rentalVehicle New field with parameters for rental vehicle activities that are part of the contract between lessor and lessee
leaseContract.rentalVehicle.inContract New field that indicates if rental vehicle activities are part of the contract between lessor and lessee
leaseContract.rentalVehicle.rentalHoursChargedToLesseeForRepairAndMaintenance New field that indicates how many hours of vehicle rent due to repair and maintenance reasons is directly charged to the lessee (after which the lessor pays)
leaseContract.rentalVehicle.rentalHoursChargedToLesseeForRepairAndMaintenance New field that indicates how many hours of vehicle rent due to (collision) damage reasons is directly charged to the lessee (after which the lessor pays)
maxDeployableRentalClass leaseContract.rentalVehicle.rentalClass Moved
leaseContract.rentalVehicle.fuelType New field that indicates what fuel premium for the replacement vehicle is part of the contract between lessor and lessee
leaseContract.rentalVehicle.surchargeEstate New field that indicates if an allowance for estate replacement vehicles is part of the contract between lessor and lessee
leaseContract.rentalVehicle.surchargeAutomaticTransmission New field that indicates if an allowance for vehicles with an automatic transmission is part of the contract between lessor and lessee
leaseContract.rentalVehicle.rentalClassesInContract New field that indicates what rental classes are part of the contract between lessor and lessee
leaseContract.rentalVehicle.rentalClassesNotInContract New field that indicates what rental classes are not part of the contract between lessor and lessee
supplierContract New field that indicates what operations are allowed for the specific supplier as configured by the lessor
supplierContract.repairAndMaintenance New field that indicates what repair and maintenance operations are allowed for the specific supplier as configured by the lessor
permissions.maintenance supplierContract.repairAndMaintenance.allowed Moved
supplierContract.repairAndMaintenance.serviceLevel New field containing information about the applicable repair and maintenance service level
supplierContract.tires New field that indicates what tire operations are allowed for the specific supplier as configured by the lessor
permissions.tires Removed. Please see the new fields supplierContract.tires.tireSwapAllowed, supplierContract.tires.tireReplaceAllowed and supplierContract.tires.tirePurchaseWithoutMountingAllowed
supplierContract.tires.tireSwapAllowed New field that indicates if the tire swap (3199) components may be submitted by the supplier for this object.
supplierContract.tires.tireReplaceAllowed New field that indicates if the tire replace (3198) components may be submitted by the supplier for this object.
supplierContract.tires.tirePurchaseWithoutMountingAllowed New field that indicates if the tire purchase without mounting (3196) components may be submitted by the supplier for this object.
permissions.usedTires supplierContract.tires.usedTiresAllowed Moved
permissions.profileDepthExemption supplierContract.tires.profileDepthRequiredExemption Moved
allowedTireCosts supplierContract.tires.allowedCosts Moved
allowedTireCosts.storageCosts supplierContract.tires.allowedCosts.tireStorageCosts Renamed
allowedTireCosts.transportCosts supplierContract.tires.allowedCosts.tireTransportCosts Renamed
allowedTireCosts.disposalFee supplierContract.tires.allowedCosts.tireDisposalFee Renamed
allowedTireCosts.trim supplierContract.tires.allowedCosts.tireTrim Renamed
allowedTireCosts.regroove supplierContract.tires.allowedCosts.tireRegroove Renamed
allowedTireCosts.balance supplierContract.tires.allowedCosts.wheelBalance Renamed
allowedTireCosts.exchange supplierContract.tires.allowedCosts.wheelExchange Renamed
supplierContract.tires.serviceLevel New field containing information about the applicable tires service level
supplierContract.rentalVehicle New field that indicates what rental vehicle operations are allowed for the specific supplier as configured by the lessor
permissions.reliefVehicle supplierContract.rentalVehicle.allowed Moved
reliefVehicleInformation leaseContract.rentalVehicle.remark Moved
supplierContract.rentalVehicle.allowedCosts New field that indicates what rental vehicle costs are allowed for the specific supplier as configured by the lessor
supplierContract.rentalVehicle.allowedCosts.deliveryCosts New field that indicates whether delivery costs are allowed for the specific supplier as configured by the lessor
supplierContract.rentalVehicle.allowedCosts.pickupCosts New field that indicates whether pickup costs are allowed for the specific supplier as configured by the lessor
supplierContract.rentalVehicle.allowedCosts.fuelServiceCosts New field that indicates whether fuel service costs are allowed for the specific supplier as configured by the lessor
supplierContract.rentalVehicle.serviceLevel New field containing information about the applicable rental vehicle service level

 {
   "isActive": true,
   "vehicle": {
       "licensePlate": "003NET",
-      "make": "-",
-      "model": "Golf",
+      "vehicleMake": "-",
+      "vehicleModel": "Golf",
       "objectType": {
           "code": "PV",
+          "objectTypeCategory": "A",
           "description": "PersonenVervoer < 9 pers."
       },
       "fuelTypeCode": {
           "code": "D",
           "description": "Diesel"
       },
-      "type": "",
       "firstRegisteredDate": "2000-01-01T00:00:00",
       "maintenance": {
           "lastMaintenanceCode": ""
       },
-      "currentTireSeasonCode": {
-          "code": "Z",
-          "description": "Zomer"
-      },
-      "currentTireCategoryCode": {
-          "code": "S",
-          "description": "Standaard"
-      },
       "tirePositions": [
           {
               "positionCode1": "1",
               "positionCode2": "L"
           },
           {
               "positionCode1": "1",
               "positionCode2": "R"
           },
           {
               "positionCode1": "2",
               "positionCode2": "L"
           },
           {
               "positionCode1": "2",
               "positionCode2": "R"
           }
       ],
       "mountedTires": [
           {
               "positionCode1": "1",
               "positionCode2": "L",
               "specifications": {
                   "id": 835877,
+                  "vacoStatus": "Current",
                   "seasonIndicator": "Summer",
                   "category": "Standard",
                   "bacCode": "DT .255.65.017.H .DH7.00",
                   "nominalWidthInMillimeters": 255,
                   "makeCode": "DT",
                   "make": "Delinte",
                   "eanCode": "6901532400181",
                   "loadIndex": 110,
                   "modelTypeProfile": "DH7",
                   "speedRating": "H",
                   "typeNumber": 0,
                   "rimDiameterInInches": 17,
                   "widthHeightRatio": 65,
                   "noiseOutputLevelInDecibels": 72.0,
                   "rollingResistanceCode": "C",
                   "wetGripCode": "C",
                   "manufacturerSuggestedRetailPrice": 115.0000,
-                  "description": "255/65 HR17 TL 110H DELINTE DH7 SUV",
-                  "isCurrent": true
+                  "description": "255/65 HR17 TL 110H DELINTE DH7 SUV"
               },
               "lastMeasuredProfileDepth": 3.0000
           }
       ],
       "storedTires": []
   },
   "lessor": {
       "number": 307246,
       "name": "Test-LM Vereniging ROB"
   },
-  "endDate": "2020-12-31T00:00:00",
-  "maximumMileage": 180000,
-  "information": "",
-  "reliefVehicleInformation": "",
-  "permissions": {
-      "maintenance": true,
-      "reliefVehicle": false,
-      "tires": true,
-      "tireSwap": true,
-      "tireReplace": true,
-      "tireWithoutMounting": true,
-      "winterTires": "IncludedInLeaseContract",
-      "usedTires": true,
-      "allSeason": "Allowed",
-      "runOnFlat": "Required",
-      "nitrogen": true,
-      "deliveryCosts": true,
-      "pickupCosts": true,
-      "fillupCosts": true,
-      "profileDepthExemption": false
-  },
-  "allowedTireCosts": {
-      "storageCosts": true,
-      "transportCosts": false,
-      "surchargeNitrogen": true,
-      "surchargeRunOnFlat": true,
-      "surchargeLargeRim": true,
-      "surchargeMobileService": true,
-      "surchargeTruckTire": false,
-      "handlingCostLessorStock": false,
-      "handlingCostThirdPartyTire": false,
-      "disposalFee": true,
-      "deliveryFeeToDealer": false,
-      "trim": false,
-      "tirematch": false,
-      "regroove": true,
-      "balance": true,
-      "exchange": false
+  "leaseContract": {
+      "endDate": "2020-12-31T00:00:00",
+      "maximumMileage": 180000,
+      "repairAndMaintenance": {
+          "inContract": true
+      },
+      "tires": {
+          "inContract": "IncludedInContract",
+          "tireSwapInContract": "IncludedInContract",
+          "rofTiresInContract": "Required",
+          "allSeasonTiresInContract": "Allowed",
+          "nitrogenTireFillingInContract": true,
+          "usedTiresInContract": true,
+          "hasTireSetForTireSwapInStorage": false
+      },
+      "rentalVehicle": {
+          "inContract": false,
+          "rentalClass": "CP",
+          "fuelType": "Diesel",
+          "surchargeEstate": false,
+          "surchargeAutomaticTransmission": false,
+          "rentalClassesInContract": [
+              {
+                  "rentalClass": "A",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "A",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "B",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "B",
+                  "fuelType": "Diesel",
+                  "forEstate": true,
+                  "freeKilometrage": 130
+              },
+              {
+                  "rentalClass": "BP",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "BP",
+                  "fuelType": "Diesel",
+                  "forEstate": true,
+                  "freeKilometrage": 130
+              },
+              {
+                  "rentalClass": "C",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "C",
+                  "fuelType": "Diesel",
+                  "forEstate": true,
+                  "freeKilometrage": 130
+              },
+              {
+                  "rentalClass": "CP",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "CP",
+                  "fuelType": "Diesel",
+                  "forEstate": true,
+                  "freeKilometrage": 130
+              },
+              {
+                  "rentalClass": "D",
+                  "fuelType": "Diesel",
+                  "forEstate": true,
+                  "freeKilometrage": 130
+              },
+              {
+                  "rentalClass": "DP",
+                  "fuelType": "Diesel",
+                  "forEstate": true,
+                  "freeKilometrage": 130
+              },
+              {
+                  "rentalClass": "EP",
+                  "fuelType": "Diesel",
+                  "forEstate": true,
+                  "freeKilometrage": 130
+              }
+          ],
+          "rentalClassesNotInContract": [
+              {
+                  "rentalClass": "A",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "B",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "B",
+                  "fuelType": "Gasoline",
+                  "forEstate": true,
+                  "freeKilometrage": 110
+              },
+              {
+                  "rentalClass": "B",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "B",
+                  "fuelType": "Electric",
+                  "forEstate": true,
+                  "freeKilometrage": 150
+              },
+              {
+                  "rentalClass": "BP",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "BP",
+                  "fuelType": "Gasoline",
+                  "forEstate": true,
+                  "freeKilometrage": 110
+              },
+              {
+                  "rentalClass": "BP",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "BP",
+                  "fuelType": "Electric",
+                  "forEstate": true,
+                  "freeKilometrage": 150
+              },
+              {
+                  "rentalClass": "C",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "C",
+                  "fuelType": "Gasoline",
+                  "forEstate": true,
+                  "freeKilometrage": 110
+              },
+              {
+                  "rentalClass": "C",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "C",
+                  "fuelType": "Electric",
+                  "forEstate": true,
+                  "freeKilometrage": 150
+              },
+              {
+                  "rentalClass": "CP",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "CP",
+                  "fuelType": "Gasoline",
+                  "forEstate": true,
+                  "freeKilometrage": 110
+              },
+              {
+                  "rentalClass": "CP",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "CP",
+                  "fuelType": "Electric",
+                  "forEstate": true,
+                  "freeKilometrage": 150
+              },
+              {
+                  "rentalClass": "D",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "D",
+                  "fuelType": "Gasoline",
+                  "forEstate": true,
+                  "freeKilometrage": 110
+              },
+              {
+                  "rentalClass": "D",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "D",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "D",
+                  "fuelType": "Electric",
+                  "forEstate": true,
+                  "freeKilometrage": 150
+              },
+              {
+                  "rentalClass": "DP",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "DP",
+                  "fuelType": "Gasoline",
+                  "forEstate": true,
+                  "freeKilometrage": 110
+              },
+              {
+                  "rentalClass": "DP",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "DP",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "DP",
+                  "fuelType": "Electric",
+                  "forEstate": true,
+                  "freeKilometrage": 150
+              },
+              {
+                  "rentalClass": "EP",
+                  "fuelType": "Gasoline",
+                  "forEstate": false,
+                  "freeKilometrage": 100
+              },
+              {
+                  "rentalClass": "EP",
+                  "fuelType": "Gasoline",
+                  "forEstate": true,
+                  "freeKilometrage": 110
+              },
+              {
+                  "rentalClass": "EP",
+                  "fuelType": "Diesel",
+                  "forEstate": false,
+                  "freeKilometrage": 120
+              },
+              {
+                  "rentalClass": "EP",
+                  "fuelType": "Electric",
+                  "forEstate": false,
+                  "freeKilometrage": 140
+              },
+              {
+                  "rentalClass": "EP",
+                  "fuelType": "Electric",
+                  "forEstate": true,
+                  "freeKilometrage": 150
+              }
+          ]
+      }
   },
-  "maxDeployableRentalClass": "CP",
-  "winterTireSetAlreadyPurchased": false
+  "supplierContract": {
+      "repairAndMaintenance": {
+          "allowed": true,
+          "serviceLevel": {
+              "href": "/v2/servicelevel/default"
+          }
+      },
+      "tires": {
+          "tireSwapAllowed": true,
+          "tireReplaceAllowed": true,
+          "tirePurchaseWithoutMountingAllowed": true,
+          "usedTiresAllowed": true,
+          "profileDepthRequiredExemption": false,
+          "allowedCosts": {
+              "tireStorageCosts": true,
+              "tireTransportCosts": false,
+              "surchargeNitrogen": true,
+              "surchargeRunOnFlat": true,
+              "surchargeLargeRim": true,
+              "surchargeMobileService": true,
+              "surchargeTruckTire": false,
+              "handlingCostLessorStock": false,
+              "handlingCostThirdPartyTire": false,
+              "tireDisposalFee": true,
+              "deliveryFeeToDealer": false,
+              "tireTrim": false,
+              "tirematch": false,
+              "tireRegroove": true,
+              "wheelBalance": true,
+              "wheelExchange": false
+          },
+          "serviceLevel": {
+              "href": "/v2/servicelevel/default"
+          }
+      },
+      "rentalVehicle": {
+          "allowed": false,
+          "allowedCosts": {
+              "deliveryCosts": true,
+              "pickupCosts": true,
+              "fuelServiceCosts": true
+          },
+          "serviceLevel": {
+              "href": "/v2/servicelevel/default"
+          }
+      }
+  }
 }
            
  • GET /v2/contracts/{licensePlate}
  • GET /v2/lessors/{lessorId}/contracts/{licensePlate}

Error Model

To provide better error handling each specific error has been given a unique code. These error codes are provided in a new field code in the error response model.

Next to encoding errors into error codes, the context of the error will also be provided in a machine readably format. Combined, both changes should make it a lot easier for REST API consumers to act more succinctly on the returned errors. See the difference below for an example in error reporting for a faulty create invoice request.


 {
   "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
   "title": "Bad Request",
   "status": 400,
   "detail": "A validation error occurred, see errors array for details",
   "traceId": "0HM9KI6HI5VPE:00000001",
   "errors": [
     {
-      "description": "Sender identity field RobNumber must have value 307247"
+      "code": "ROB-INV000010",
+      "description": "Sender identity field RobNumber must have value 307247",
+      "context": {
+        "fieldName": "RobNumber"
+      }
     },
     {
-      "description": "Only the outstanding amount of 0.00 (excluding VAT) may be invoiced as debit"
+      "code": "ROB-INV000018",
+      "description": "Only the outstanding amount of 0.00 (excluding VAT) may be invoiced as debit",
+      "context": {}
     }
   ]
 }
            

Lessors

The optional rental phone number field has been added to the list of phone numbers returned per lessor when fetching all known ROB-Net lessors.


 {
   "number": 306862,
   "name": "RiemersmaLeasing",
+  "active": true,
   "address": {
     "street": "de Waterman",
     "streetNumber": "7A",
     "postalCode": "5215MX",
     "city": "'s-Hertogenbosch"
   },
   "contact": "",
   "phone": {
     "general": "073-8504750 ",
     "maintenance": "            ",
     "damage": "            "
   },
   "paymentInformation": {
     "iban": "",
     "bic": "",
     "vatNumber": ""
   },
   "subLessors": []
 },
 {
   "number": 307246,
   "name": "Test-LM Vereniging ROB",
   "address": {
     "street": "",
     "streetNumber": "",
     "postalCode": "",
     "city": ""
   },
   "contact": "",
   "phone": {
     "general": "0306595297",
     "maintenance": "0306595299",
     "damage": "0306595298",
+    "rental": "061234567"
   },
   "paymentInformation": {
     "iban": "NL13TEST0123456789",
     "bic": "TESTNL2A",
     "vatNumber": "NL001234567B01"
   },
   "subLessors": [
     ...
   ]
 },

            
  • GET /v2/lessors

Service Request

Appointment Field

Please see the request change entry for details.


 {
-  "date": "2021-06-16T00:00:00Z",
+  "workshopDate": "2021-06-16",
   "workOrderNumber": "werkbon-12",
   "contact": {
     "name": "Piet van Putten",
     "phone": "+316543210"
   },
   "estimatedDurationInDays": 3
 }
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

Component Location Field

If in a component or subcomponent no location is given instead of returning an empty array the field location will no longer be present.


 {
   "id": "886175f0-f552-4ce3-a1fa-81ffbb97d888",
   "rob": {
     "code": "3156",
     "description": "Verwijderingsbijdrage"
   },
-  "operation": {},
-  "location": [],
-  "reason": {},
   "price": 2.0
 }
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Component Operation Field

If in a component or subcomponent no operation is given instead of returning an empty JSON object the field operation will no longer be present.


 {
   "id": "886175f0-f552-4ce3-a1fa-81ffbb97d888",
   "rob": {
     "code": "3156",
     "description": "Verwijderingsbijdrage"
   },
-  "operation": {},
-  "location": [],
-  "reason": {},
   "price": 2.0
 }
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Component Part Field

Please see the request change entry for details.


 {
   "id": "3f5c7272-bb74-4803-860a-361b5d9a404e",
   "rob": {
     "code": "3101",
     "description": "Band"
   },
   "operation": {
     "code": "08",
     "description": "Controleren"
   },
-  "location": [],
-  "reason": {},
-  "value": 2.0,
+  "value": "2",
   "part": {
+    "partType": "Tire",
     "id": 835877,
-    "selectState": "Active",
+    "vacoStatus": "Current",
     "seasonIndicator": "Summer",
     "category": "Standard",
     "makeCode": "DT",
     "nominalWidthInMillimeters": 255,
     "widthHeightRatio": 65,
     "rimDiameterInInches": 17,
     "loadIndex": 110,
     "speedRating": "H",
     "modelTypeProfile": "DH7",
     "typeNumber": 0,
     "noiseOutputLevelInDecibels": 72.0,
     "rollingResistanceCode": "C",
     "wetGripCode": "C",
     "manufacturerSuggestedRetailPrice": 115.0000,
     "description": "255/65 HR17 TL 110H DELINTE DH7 SUV",
     "bacCode": "DT .255.65.017.H .DH7.00",
     "eanCode": "6901532400181"
   }
 },
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Component Reason Field

The field reason in a component is no longer optional.

  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Component Status Field

The status field in the service request response components used to contain an untyped field code representing the current line status but now uses a fixed enumeration.

On top of that, the value ProvisionallyApproved has been added. This status represents a provisional approval the lessor may give for a service request line that is not yet complete but is accepted as is thus far. This new status will be used by the new rental vehicle model.

The status field in the service request response subcomponents has been given its own enum in order to support the new rental vehicle model. This model will be the first to utilize the new subcomponent status field.

There is no JSON difference to show due to the new enum values using the same string representations. However, the possible values have been slightly altered and can be observed in the mapping below. This mapping only applies to the values of the components field status.code. For subcomponents no mapping is provided as those were unused in the v1 API.

Version 1 Version 2
Entered Entered
Changed Changed
Lessor ApprovalRequested
Approved Approved
ProvisionallyApproved
CallLessor CallLessor
Denied Denied
LessorWillCall LessorWillCall
Cancelled Cancelled
CancellationApproved CancellationApproved
CancellationDenied CancellationDenied
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Component Tire Part

In order to better reflect the purpose of the field selectState has been renamed to vacoStatus. This field only serves to indicate whether the tire is on the VACO list and available for direct purchase at the manufacturer.

The mapping below will show how the selectState field values translate to the new vacoStatus field.

SelectState Value VacoStatus Value
Active Current
Inactive Obsolete
Obsolete Obsolete

 {
+  "partType": "Tire",
   "id": 835877,
-  "selectState": "Active",
+  "vacoStatus": "Current",
   "seasonIndicator": "Summer",
   "category": "Standard",
   "makeCode": "DT",
   "nominalWidthInMillimeters": 255,
   "widthHeightRatio": 65,
   "rimDiameterInInches": 17,
   "loadIndex": 110,
   "speedRating": "H",
   "modelTypeProfile": "DH7",
   "typeNumber": 0,
   "noiseOutputLevelInDecibels": 72.0,
   "rollingResistanceCode": "C",
   "wetGripCode": "C",
   "manufacturerSuggestedRetailPrice": 115.0000,
   "description": "255/65 HR17 TL 110H DELINTE DH7 SUV",
   "bacCode": "DT .255.65.017.H .DH7.00",
   "eanCode": "6901532400181"
 }
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Component Value Field

Please see the request change entry for details.


 {
   "id": "72870000-d0c3-9eb6-000a-08d7c74a44bb",
   "rob": {
       "code": "5401",
       "description": "Kilometerteller"
   },
   "supplierCode": "",
   "operation": {
       "code": "19",
       "description": "Aflezen"
   },
-  "location": [],
   "reason": {
       "code": "99",
       "description": "n.v.t."
   },
-  "value": 10000.0,
+  "value": "10000",
   "price": 0.00,
   "status": {
       "code": "Entered",
       "description": "Ingevoerd"
   }
 },
            
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • GET /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Components Field

Please see the request change entry for details.


 "components": [
   {
     "id": "72870000-d0c3-9eb6-2e46-08d937174b75",
     "rob": {
       "code": "3198",
       "description": "Bandvervanging"
     },
     "supplierCode": "",
     "operation": {
       "code": "00",
       "description": "Uitvoeren"
     },
-    "location": [],
     "reason": {
       "code": "99",
       "description": "n.v.t."
     },
     "price": 102.00,
     "status": {
       "code": "Entered",
       "description": "Ingevoerd"
     },
-    "components": [
+    "subcomponents": [
       {
         "id": "84a3f5db-1aa7-4f71-aca1-34cc66b71c71",
         "rob": {
           "code": "3101",
           "description": "Band"
         },
         "operation": {
           "code": "01",
           "description": "Vervangen"
         },
         "location": [
           "1",
           "L"
         ],
-        "reason": {},
         "price": 11.0,
-        "components": [
+        "subcomponents": [
            ...
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Invoices Field

The field invoices of each service request response contains information about the ROB-Net invoicing process. However, the name did not encompass all information with regard to invoicing thus the field invoices has been renamed to invoicing to reflect the more general concept it represents instead of a set of invoices.

Secondly, the field totalAmountApproved has been added to make the invoicing data set complete. See the difference below for an overview of the changes in the response.


   ...
-  "invoices": {
+  "invoicing": {
     "status": "ReadyForInvoicing",
+    "totalAmountApproved": 102.00,
     "totalAmountToInvoice": 102.00,
     "totalAmountInvoiced": 0.00
   }
 }
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Lessor Service Request Number Field

The field LessorServiceRequestNumber has been renamed to ServiceRequestNumber in order to stay in line with the response structure of the new get service requests response.


 {
   "data": {
-    "version": "2019-08-01",
-    "revision": 1,
     "id": "344e0000-5daa-0015-07b1-08d93f993880",
     "creationTimeStamp": "2021-07-05T09:42:36.01",
     "status": "Approved",
     "readOnly": false,
     "supplierId": 307247,
     "lessorId": 307246,
-    "lessorServiceRequestNumber": 16315,
+    "serviceRequestNumber": 16315,
     "licensePlate": "001NET",
     ...
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

Status Field

The status field in the service request response used to contain an untyped field code representing the current service request status. This field has been converted to use the same enum as the request model.

On top of that, the value ProvisionallyApproved has been added. This status represents a provisional approval the lessor may give for a service request line that is not yet complete but is accepted as is thus far. This new status does not allow invoicing and will be used by the new rental vehicle model.

There is no JSON difference to show due to the new enum values using the same string representations. However, the possible values have been slightly altered and can be observed in the mapping below.

Version 1 Version 2
Draft Draft
Modified Modified
Lessor ApprovalRequested
Approved Approved
ProvisionallyApproved
Denied Denied
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

Subcomponent Reason Field

If in a subcomponent no reason is given instead of returning an empty JSON object the field reason will no longer be present.


 {
   "id": "886175f0-f552-4ce3-a1fa-81ffbb97d888",
   "rob": {
     "code": "3156",
     "description": "Verwijderingsbijdrage"
   },
-  "operation": {},
-  "location": [],
-  "reason": {},
   "price": 2.0
 }
            

Sublessor Code Field

The optional sublessorCode field has been added to the service request response(s). Including this in the response enables the API consumer to identify the owner of the object identified by the licensePlate, lessorId fields and optionally the sublessorCode field without having to refer to GET /v2/contracts/{licensePlate}.

If no sublessor is associated with the object the field will not be returned. See the difference below for an example where the object is associated with a sublessor.


 {
   "data": {
-    "version": "2019-08-01",
-    "revision": 1,
     "id": "344e0000-5daa-0015-07b1-08d93f993880",
     "creationTimeStamp": "2021-07-05T09:42:36.01",
     "status": "Approved",
     "readOnly": false,
     "supplierId": 307247,
     "lessorId": 307246,
+    "sublessorCode": "SUBLM-01",
-    "lessorServiceRequestNumber": 16315,
+    "serviceRequestNumber": 16315,
     "licensePlate": "001NET",
     ...
            
  • GET /v2/servicerequests/{id}
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

TotalAmountApproved Field

The TotalAmountApproved field has been moved to the Invoices field

  • GET /v2/servicerequests/{id}

Service Requests

The service requests method response model has been overhauled to match more closely the existing GET /v2/requests method. This method is to be fully replaced by the aforementioned one once relief vehicle request support has been phased out.

Along with the model changes the URL query parameter containsRobCode has been dropped in favour of the new URL query parameter licensePlate. Full details can be found in the API details.

Finally, a new field hasMore has been added indicating whether there are more service requests available to fetch. This field remains valid if any of the optional URL query parameters have been specified.


 {
-  "links": [],
   "serviceRequests": [
     {
+      "href": "/v2/servicerequests/344e0000-5daa-0015-07b1-08d93f993880",
       "id": "344e0000-5daa-0015-07b1-08d93f993880",
-      "status": "Approved"
+      "lastModifiedUtc": "2021-07-05T12:28:22.37",
+      "lessorId": 307246,
+      "lessorName": "Test-LM Vereniging ROB",
+      "serviceRequestNumber": 16315,
+      "supplierId": 307247,
+      "licensePlate": "001NET",
+      "workOrderNumber": "WB-004",
+      "status": "Approved",
+      "invoicing": {
+        "status": "ReadyForInvoicing",
+        "totalAmountApproved": 102.00,
+        "totalAmountToInvoice": 102.00,
+        "totalAmountInvoiced": 0.00
+      }
     }
-  ]
+  ],
+  "hasMore": false
 }
            
  • GET /v2/servicerequests

Tires

Tire

Due to the same change as described for the service request tire part response model the tire model yield by the two supported tire search methods now uses the new fields vacoStatus and obsoleteVacoStatusSinceYear instead of the old fields isCurrent and notCurrentSinceYear.


 {
   "id": 22517,
+  "vacoStatus": "Obsolete",
+  "obsoleteVacoStatusSinceYear": 2013,
   "seasonIndicator": "Summer",
   "category": "Standard",
   "bacCode": "",
   "nominalWidthInMillimeters": 245,
   "makeCode": "PI",
   "make": "Pirelli",
   "eanCode": "",
   "loadIndex": 95,
   "modelTypeProfile": "ZEN",
   "speedRating": "Y",
   "typeNumber": 0,
   "rimDiameterInInches": 20,
   "widthHeightRatio": 35,
   "noiseOutputLevelInDecibels": 0.0,
   "rollingResistanceCode": "",
   "wetGripCode": "",
   "manufacturerSuggestedRetailPrice": 500.5000,
-  "description": "PIRELLI   PZERO NERO 95Y   TL  XL",
-  "isCurrent": false,
-  "notCurrentSinceYear": 2013
+  "description": "PIRELLI   PZERO NERO 95Y   TL  XL"
 }
            
  • GET /v2/tire
  • GET /v2/tires

Response Code Changes

Invoice Attachment

Uploading a PDF as invoice attachment previously yielded the HTTP status code 200 OK. It now returns the HTTP status code 201 Created to better reflect the outcome of the HTTP request. In addition it now also includes the location of the created resource in the Location HTTP response header.

  • PUT /v2/servicerequests/{id}/invoices/{invoiceId}/pdf

Invoice Creation

Creating an invoice previously yielded the HTTP status code 200 OK. It now returns the HTTP status code 201 Created to better reflect the outcome of the HTTP request. In addition it now also includes the location of the created resource in the Location HTTP response header.

  • POST /v2/servicerequests/{id}/invoices

Invoice Status

Supplying the reason for not invoicing through ROB-Net previously yielded the HTTP status code 200 OK. It now returns the HTTP status code 204 No Content to better reflect the outcome of the HTTP request.

  • POST /v2/servicerequests/{id}/invoices/status

Service Request

Fetching, updating, overwriting or deleting an already archived service request previously yielded the HTTP status code 404 Not Found. It now returns the HTTP status code 410 Gone to communicate that the service request has been archived. Note that the invoicing methods can still be used for this service request.

  • GET /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • DELETE /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{requestId}/components/{componentId}
  • POST /v2/servicerequests/{requestId}/components/{componentId}/cancel
  • DELETE /v2/servicerequests/{requestId}/components/{componentId}

Service Request Line

Creating a service request line previously yielded the HTTP status code 200 OK. It now returns the HTTP status code 201 Created to better reflect the outcome of the HTTP request. In addition it now also includes the location of the created resource in the Location HTTP response header.

Note that updating or overwriting a service request line still yields the HTTP status code 200 OK.

  • POST /v2/servicerequests/{id}/components/{componentId}

Validation Changes

Appointment Dates

Both the workshopDate as the checkoutDate, as defined in the request model Appointment Field change, now use a validation on the year. The year of each field must be at least 2000 or a maximum 2100.

Validation will occur both at initial submission, for example by creating a service request , and when requesting approval. This last additional validation is necessary due to the service request possibly being made through the previous version API.

  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

Duplicate Components

Some components are allowed to be repeated multiple times, such as the swap tire at position subcomponent part of the tire swap (ROB-code 3199) component. Most however are not. In some cases those would accidentally be accepted. The validation has been reworked to no longer accept these invalid duplicate occurrences.

  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Invoice Creation

The validation rules for invoice creation have been revised to be better reflected by the OpenAPI specifications, as can be observed here. In particular the fields, and their sub fields, vatLines and total are now correctly marked as required and include constraints for the numeric values.

  • POST /v2/servicerequests/{id}/invoices

License Plate

Validation of the licensePlate field within the vehicle object is now done through pattern matching. See the affected methods below or view the new requirement in the OpenAPI specifications.

  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

Multiple Service Requests

With the introduction of rental vehicle lines the potential need for multiple open service requests for the same object for a single supplier arose. The API now allows two simultaneous service requests with the rule that only one of them contains a rental vehicle line and the other only contains repair and maintenance and/or tire lines. In practice this will allow:

  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Required Components

All of the allowed components with subcomponents, as can be observed through the method GET /v2/components, have requirements in place for the hierarchy. That is, the parent component has constraints what child subcomponents must be present or absent and the valid combinations of these.

With the introduction of the rental vehicle components more sophisticated checking was required and has been retroactively applied to all other subcomponents requirement validations. This impacts a few rare cases of previously wrongfully allowed subcomponent combinations below the tire components.

  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Required Draft Fields

To make the draft phase more flexible the number of required fields to create a service request with the draft status has been minimized. The difference below shows what a bare bones service request looks like in version 2 in contrast to version 1.

Requesting approval will still demand valid values to be present for these fields which is why the PUT and PATCH service request methods now also allow supplying the vehicle field. The approval PATCH request call below shows the additions required to make a valid submittable service request.


 {
-  "version": "2019-08-01",
-  "revision": 1,
   "status": "Draft",
-  "supplierId": 307247,
   "appointment": {
-    "date": "2021-04-29T00:00:00Z",
     "supplierNumber": "WB-101",
-    "estimatedDurationInDays": 1,
     "contact": {
       "name": "Werkplaats",
       "phone": "06-12345678"
     }
   },
   "vehicle": {
-    "licensePlate": "003NET",
-    "partialVin": "0000"
+    "licensePlate": "003NET"
   },
   "components": []
 }
            

{
  "appointment": {
    "workshopDate": "2021-04-29",
    "supplierNumber": "WB-101",
    "contact": {
      "name": "Werkplaats",
      "phone": "06-12345678"
    },
    "estimatedDurationInDays": 1
  },
  "vehicle": {
    "licensePlate": "003NET",
    "partialVin": "0000"
  },
  "status": "ApprovalRequested",
  "components": [
    {
      "id": "00000000-0000-0000-0000-000000000001",
      "rob": {
        "code": "5401"
      },
      "operation": {
        "code": "19"
      },
      "reason": {
        "code": "99"
      },
      "value": "200000"
    },
    {
      "id": "00000000-0000-0000-0000-000000000002",
      "rob": {
        "code": "1001"
      },
      "operation": {
        "code": "00"
      },
      "reason": {
        "code": "99"
      },
      "price": 40
    }
  ]
}
            
  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}

ROB Combinations

The (sub)component ROB-code combination fields rob.code, operation.code, operation.type.code and reason.code now all use regular expression pattern match validation. The expected patterns can be found in the specifications.

  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}

Subcomponent location

The location field of a subcomponent no longer allows a value, other than null or undefined, when the field is not allowed.

Previously it was allowed to be either an empty array, null or undefined when the field was not allowed. This conflicted with the more strict checking of the component location field which either allowed a valid location or no value.

  • POST /v2/servicerequests
  • PUT /v2/servicerequests/{id}
  • PATCH /v2/servicerequests/{id}
  • PUT /v2/servicerequests/{id}/components/{componentId}