Log in Book a demo

Developers

Vehicle data APIs. Built on 35 years of automotive inspections.

The B.U.S. platform exposes APIs for vehicle appraisals, condition reports and AI-powered vehicle intelligence. Open sandbox with test data and OpenAPI documentation for the REST endpoints. Contact us and we'll send you login details. Start building in minutes, not weeks.

Development at B.U.S.

Start in three steps

  1. See what’s available

    The API catalogue shows available endpoints with documentation, schemas and working examples.

  2. Build in sandbox

    Open sandbox environment with real test data. Contact us and we'll send a username, password and API key you can test with. It costs nothing.

  3. Go to production

    When you're ready, email support@bus.no with your company details, what you will use the API for and your expected volume. Approval takes two business days. We validate the setup and hand over the production keys.

API catalogue

GraphQL. Predicted defects for a vehicle

Oscar Inspector, the fastest way in

Predicted defects and maintenance needs based on make, model and mileage. Built on 20 million+ real inspections. One query, one response, and you have AI-powered vehicle intelligence in your product. This is the API most partners start with. Used by insurers for risk assessment, marketplaces for listing enrichment, leasing companies for fleet maintenance, and workshop systems for pre-visit intelligence.

See the Oscar Inspector API methods

Test. Appraisal and condition data

Damage assessments, repair costs, spare part prices and complete condition reports. Use it for sales support integration, warranty assessment, pricing models, or anywhere you need structured vehicle condition data.

See every method in the Test API

More APIs

The catalogue is growing.

Oscar Inspector API

AI-driven fault predictions for a vehicle. Same authentication as the Test API - use applicationId 5 when you fetch a token with token_ApplyToken2. Oscar Inspector has its own endpoint and its own schema, separate from the Test API. The examples show the query; the response depends on the vehicle.

Authentication

Every call sends two headers: Authorization: Bearer <accessToken> and x-api-key: <apiKey>. The API key is a separate, long-lived key issued by us. Sandbox keys are issued on request. This is where you get and renew tokens.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/SecurityPortal/BUS.APIs.GraphQLServer.P3.SecurityPortal.Endpoint1
Production https://bus2.bus.no/BUSPlatform3/SecurityPortal/BUS.APIs.GraphQLServer.P3.SecurityPortal.Endpoint1
Query token_ApplyToken2 Gets an id token, access token and refresh token for a user and an application.

Parameters

username: String!
password: String!
apiKey: String!
applicationId: Int!

Response

idToken: String
accessToken: String
refreshToken: String

Notes

  • Oscar Inspector requires applicationId 5. The Test API uses a different applicationId.
  • accessToken is valid for 60 minutes. refreshToken is valid for 90 days.
  • To renew, call token_RefreshToken with the refreshToken. Do not call token_ApplyToken2 again on every expiry.
  • If the refreshToken has expired, fetch a whole new set with token_ApplyToken2.

Example

query {
  token_ApplyToken2(
    username: ""
    password: ""
    apiKey: ""
    applicationId: 5
  ) {
    idToken
    accessToken
    refreshToken
  }
}

Example response

{
  "data": {
    "token_ApplyToken2": {
      "idToken": "",
      "accessToken": "",
      "refreshToken": ""
    }
  }
}
Query token_RefreshToken Renews the tokens with a refresh token, without signing in again.

Parameters

apiKey: String!
applicationId: Int!
refreshToken: String!

Response

idToken: String
accessToken: String
refreshToken: String

Notes

  • accessToken is valid for 60 minutes. refreshToken is valid for 90 days.
  • If the refreshToken has expired, fetch a whole new set with token_ApplyToken2.

Example

query {
  token_RefreshToken(
    apiKey: "",
    applicationId: 5,
    refreshToken: ""
    ){
      idToken
      accessToken
      refreshToken
    }
}

Example response

{
  "data": {
    "token_RefreshToken": {
      "idToken": "",
      "accessToken": "",
      "refreshToken": ""
    }
  }
}

Defect prediction

Predicted defects and maintenance needs based on registration number and mileage.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/BUSDataPortal/BUS.APIs.GraphQLServer.P3.BUSDataPortal.ExternalEndpoint1
Production https://bus2.bus.no/BUSPlatform3/BUSDataPortal/BUS.APIs.GraphQLServer.P3.BUSDataPortal.ExternalEndpoint1
Query busData_GetDefectPredictions Returns predicted defects for a vehicle, with probability and explanation per defect.

Parameters

requestId: String?
regNo: String
mileage: Int!
valuationId: Int?
inspectionId: Int?
language: String?
isMileageSuggestion: Boolean!
windowSize: Int!
refNo: String?

Response

result: DefectPredictionOutput

Notes

  • requestId from the response is used as originalRequestId in busData_RecordUserFeedback.

Example

query {
  busData_GetDefectPredictions(
    requestId: "8ef2a2d7-4373-4f93-b57e-d151a192edad"
    regNo: "CF66983"
    mileage: 50000
  ) {
    requestId
    noOfPredictions
    defectPredictions {
      checkpointTypeGroupId
      checkpointTypeGroup
      probability
    }
    errorCodes
  }
}

Example response

{
  "data": {
    "busData_GetDefectPredictions": {
      "requestId": "8ef2a2d7-4373-4f93-b57e-d151a192edad",
      "noOfPredictions": 10,
      "defectPredictions": [
        {
          "checkpointTypeGroupId": 1061,
          "checkpointTypeGroup": "Bremsetromler, bremseskiver: Trommel eller skive har for stor slitasje, med synlige-/for store riper eller sprekker, ikke tilstrekkelig festet eller brukket",
          "probability": 11.320754716981131
        }
      ],
      "errorCodes": null
    }
  }
}

Feedback

Record whether the prediction was right, and fetch the reasons that can be given.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/BUSDataPortal/BUS.APIs.GraphQLServer.P3.BUSDataPortal.ExternalEndpoint1
Production https://bus2.bus.no/BUSPlatform3/BUSDataPortal/BUS.APIs.GraphQLServer.P3.BUSDataPortal.ExternalEndpoint1
Query busData_GetUserFeedbackReasons Lists the reasons a user can give when a prediction was wrong.

Parameters

requestId: String?

Response

result: UserFeedbackReasonOutput

Notes

  • userFeedbackReasonId is used as a value in userFeedbackReasons on busData_RecordUserFeedback.

Example

query {
  busData_GetUserFeedbackReasons(requestId: "4c84c8db-3f1f-427c-b2ad-f00725f430b9") {
    requestId
    userFeedbackReasons {
      userFeedbackReasonId
      displayString
      userFeedbackReasonType
    }
    errorCodes
  }
}

Example response

{
  "data": {
    "busData_GetUserFeedbackReasons": {
      "requestId": "4c84c8db-3f1f-427c-b2ad-f00725f430b9",
      "userFeedbackReasons": [
        {
          "userFeedbackReasonId": 2000,
          "displayString": "Tidsbesparende",
          "userFeedbackReasonType": 1
        },
        {
          "userFeedbackReasonId": 2001,
          "displayString": "Høy treffsikkerhet",
          "userFeedbackReasonType": 1
        }
      ],
      "errorCodes": null
    }
  }
}
Mutation busData_RecordUserFeedback Records feedback on an earlier prediction.

Parameters

requestId: String?
originalRequestId: String?
isSatisfied: Boolean!
timeTakenForFeedback: Int!
userId: Int!
username: String?
organizationId: Int!
organizationName: String?
userFeedbackReasons: [Int]
time: DateTime?

Response

result: RecordUserFeedbackOutput

Example

mutation {
  busData_RecordUserFeedback(
    requestId: "1e692aa0-5a9b-400f-beef-7a53e27d26a2"
    originalRequestId: "8ef2a2d7-4373-4f93-b57e-d151a192edad"
    isSatisfied: true
    organizationId: 1
    organizationName: "unit 1"
    timeTakenForFeedback: 3000
    userId: 2
    username: "Nuwan"
    userFeedbackReasons: [2, 3]
  ) {
    requestId
    errorCodes
  }
}

Example response

{
  "data": {
    "busData_RecordUserFeedback": {
      "requestId": "1e692aa0-5a9b-400f-beef-7a53e27d26a2",
      "errorCodes": null
    }
  }
}

Data models

The types used in parameters and responses.

DefectPredictionOutput
RequestId: String
NoOfPredictions: Int
DefectPredictions: [DefectPrediction]
MileageSuggestions: [Int]
ErrorCodes: [Int]
TimeElapsed: Decimal
DefectPrediction
CheckpointTypeGroupId: Int
CheckpointTypeGroup: String?
CheckPointTypeGroupDescription: String?
Probability: Decimal
Explanation: String?
ConfidenceThreshold: Decimal
Function: String?
WindowSize: Int
UserFeedbackReasonOutput
RequestId: String
UserFeedbackReasons: [UserFeedbackReason]
ErrorCodes: [Int]
UserFeedbackReason
UserFeedbackReasonId: Int
DisplayString: String?
UserFeedbackReasonType: Int
RecordUserFeedbackOutput
RequestId: String
ErrorCodes: [Int]

API reference. Test, appraisal and condition report

Every method in the Test API, grouped by use. Open a method to see its parameters, its response and an example you can run.

Authentication

Every call sends two headers: Authorization: Bearer <accessToken> and x-api-key: <apiKey>. The API key is a separate, long-lived key issued by us. Sandbox keys are issued on request. This is where you get and renew tokens.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/SecurityPortal/BUS.APIs.GraphQLServer.P3.SecurityPortal.Endpoint1
Production https://bus2.bus.no/BUSPlatform3/SecurityPortal/BUS.APIs.GraphQLServer.P3.SecurityPortal.Endpoint1
Query token_ApplyToken2 Gets an id token, access token and refresh token for a user and an application.

Parameters

username: String!
password: String!
apiKey: String!
applicationId: Int!

Response

idToken: String
accessToken: String
refreshToken: String

Notes

  • accessToken is valid for 60 minutes. refreshToken is valid for 90 days.
  • To renew, call token_RefreshToken with the refreshToken. Do not call token_ApplyToken2 again on every expiry.
  • If the refreshToken has expired, fetch a whole new set with token_ApplyToken2.

Example

query {
  token_ApplyToken2(
    username: ""
    password: ""
    apiKey: ""
    applicationId: 13
  ) {
    idToken
    accessToken
    refreshToken
  }
}

Example response

{
  "data": {
    "token_ApplyToken2": {
      "idToken": "",
      "accessToken": "",
      "refreshToken": ""
    }
  }
}
Query token_RefreshToken Renews the tokens with a refresh token, without signing in again.

Parameters

apiKey: String!
applicationId: Int!
refreshToken: String!

Response

idToken: String
accessToken: String
refreshToken: String

Notes

  • accessToken is valid for 60 minutes. refreshToken is valid for 90 days.
  • If the refreshToken has expired, fetch a whole new set with token_ApplyToken2.

Example

query {
  token_RefreshToken(
    apiKey: "",
    applicationId: 13,
    refreshToken: ""
    ){
      idToken
      accessToken
      refreshToken
    }
}

Example response

{
  "data": {
    "token_RefreshToken": {
      "idToken": "",
      "accessToken": "",
      "refreshToken": ""
    }
  }
}

Appraisals

Create, read, update and list appraisals, with vehicle data, lease data and reports. The examples below use registration numbers and IDs that exist in the test environment. Ask us when you request test credentials and we will send test data that matches your account.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Production https://bus2.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Mutation Test_CreateTest Creates a new appraisal for a vehicle. Returns the appraisal id.

Parameters

vehicleDataModel: VehicleDataModel!
testDataModel: TestDataModel!

Required

  • testTypeIds
  • unitId
  • regNo / vin

Response

result: Int

Example

mutation{
  test_CreateTest(testDataModel:  {
    testTypeIds: [ 3 ],
    unitId: 1,
    externalReferenceId: "454532",
    mileage: 45000,
    testAnnotations: ["Fleet"]
    serviceData: [ {
       mileage: 2000,
       date: "2022-04-05"
    },
    {
       mileage: 10000,
       date: "2023-06-23"
    }],
    testComments: ["This is comment 1", "This is comment 2"],
    testOrderedBy: "FirstName LastName"
  },
  vehicleDataModel:  {
    regNo: "",
    vin: "YV1DZARCDH2231635",
    trimLevel: "M Sport",
    vehiclePackages: [ {
       packageName: "Comfort package",
       vehicleOptions: [ {
          optionName: "Dragkrok, elektrisk",
          includedItems: "Stabilitetsprogram släp\nVikter: totalvikt (kg): 3 500"
       }]
    }],
    vehicleOptions: [ {
        optionName: "Adaptiva LED strålkastare",
        includedItems: "Kurvljus\nLED-detaljljus"
    }]
  }
  )
}

Example response

{
  "data": {
    "test_CreateTest": 54
  }
}
Mutation testData_CreateLeaseData Adds lease data to an appraisal: product type, purchase price, contract reference and more.

Parameters

testId: Int!
leaseDataModel: LeaseDataModel!

Response

result: Boolean

Example

mutation{
  testData_CreateLeaseData(testId: 21, leaseDataModel:  {
     productType: "Full Service Leasing (FSL-SE)",
     purchasePrice: 23.50,
     quotationTemplate: "Release plus commercial",
     repairMaintenance: "Included",
     transportDate: "2025-01-21",
     winterTyres: "Not Included",
     contractReference: "777777"
  }
  )
}

Example response

{
  "data": {
    "testData_CreateLeaseData": true
  }
}
Mutation testData_CreateLeaseUserData Adds the lease customer and contacts to an appraisal: fleet manager, driver and more.

Parameters

testId: Int!
leaseUserDataModel: LeaseUserDataModel!

Response

result: Boolean

Example

mutation{
  testData_CreateLeaseUserData(testId: 21, leaseUserDataModel:  {
    customerId: "500000",
    customerName: "customer",
    fleetManagerName: "fleet manager",
    fleetManagerEmail: "fleetManager@test.com",
    installationRecipientEmail: "installationRecipient@test.com",
    kamName: "KAM Name",
    kamEmail: "kam@test.com",
    driverName: "driver",
    driverPhone: "944998989",
    driverEmail: "driver@test.com"
  }
  )
}

Example response

{
  "data": {
    "testData_CreateLeaseUserData": true
  }
}
Query Test_GetTest Gets an appraisal with its status, mileage and service history.

Parameters

testId: Int!

Response

result: TestDataModel

Notes

  • Localized text fields such as testStatus and checkpoint names are returned in the caller's culture. The culture is taken from the token's culture claim, falling back to Accept-Language. The example was captured with Swedish culture.

Example

query{
  test_GetTest(testId: 32685)
  {
    testId,
    externalReferenceId,
    mileage,
    serviceData {
      date,
      mileage,
      comment
    },
    unitId,
    testTypeIds,
    testStatus,
    testComments
  }
}

Example response

{
  "data": {
    "test_GetTest": {
      "testId": 59,
      "externalReferenceId": "45678",
      "mileage": 45000,
      "serviceData": [
        {
          "date": "2022-04-04T18:30:00.000Z",
          "mileage": 2000,
          "comment": null
        },
        {
          "date": "2023-06-22T18:30:00.000Z",
          "mileage": 10000,
          "comment": null
        }
      ],
      "unitId": 1,
      "testTypeIds": [
        2
      ],
      "testStatus": "Test påbörjad",
      "testComments": []
    }
  }
}
Query Test_GetTestFiles Gets the images and files that belong to an appraisal.

Parameters

testId: Int!

Response

result: [TestFileModel]

Example

query{
  test_GetTestFiles(testId: 32685)
  {
    fileUrl,
    fileName,
    testSectionId,
    mediaId
  }
}

Example response

{
  "data": {
    "test_GetTestFiles": [
      {
        "fileUrl": "https://…/fil.jpg?sv=…&sig=…",
        "fileName": "image (9).jpg",
        "testSectionId": 6,
        "mediaId": "CD......"
      },
      {
        "fileUrl": "https://…/fil.jpg?sv=…&sig=…",
        "fileName": "image (10).jpg",
        "testSectionId": 6,
        "mediaId": "CD......"
      },
      {
        "fileUrl": "https://…/fil.jpg?sv=…&sig=…",
        "fileName": "image (17).jpg",
        "testSectionId": 1,
        "mediaId": "CD......"
      }
    ]
  }
}
Query TestData_GetVehicleData Gets the vehicle data: registration number, VIN, options and packages.

Parameters

testId: Int!

Response

result: VehicleDataModel

Example

query{
  testData_GetVehicleData(testId: 59)
  {
    regNo,
    vin,
    trimLevel,
    vehicleOptions {
      optionName,
      includedItems,
      isSelected
    },
    vehiclePackages {
      packageName,
      isSelected,
      vehicleOptions {
        optionName,
        includedItems,
        isSelected
      }
    }
    color,
    model,
    make,
    gearBox,
    engine,
    inspectionDueDate,
    lastInspectedDate
  }
}

Example response

{
  "data": {
    "testData_GetVehicleData": {
      "regNo": "YSA053",
      "vin": "YV1DZARCDH2231635",
      "trimLevel": "M Sport",
      "vehicleOptions": [
        {
          "optionName": "Adaptiva LED strålkastare",
          "includedItems": "Kurvljus\nLED-detaljljus",
          "isSelected": false
        }
      ],
      "vehiclePackages": [
        {
          "packageName": "Comfort package",
          "isSelected": false,
          "vehicleOptions": [
            {
              "optionName": "Dragkrok, elektrisk",
              "includedItems": "Stabilitetsprogram släp\nVikter: totalvikt (kg): 3 500",
              "isSelected": false
            }
          ]
        }
      ],
      "color": "Svart",
      "model": "XC60",
      "make": "Volvo",
      "gearBox": "Automat",
      "engine": "2.0 D3 D4204T9 (110 kW)",
      "inspectionDueDate": "2027-07-30T22:00:00.000Z",
      "lastInspectedDate": "2025-07-21T22:00:00.000Z"
    }
  }
}
Query testData_GetLeaseData Gets the lease data for an appraisal.

Parameters

testId: Int!

Response

result: LeaseDataModel

Example

query{
  testData_GetLeaseData(testId: 21) {
     productType
     purchasePrice
     quotationTemplate
     repairMaintenance
     transportDate
     winterTyres
  }
}

Example response

{
  "data": {
    "testData_GetLeaseData": {
      "productType": null,
      "purchasePrice": null,
      "quotationTemplate": null,
      "repairMaintenance": null,
      "transportDate": null,
      "winterTires": null
    }
  }
}
Query testData_GetLeaseUserData Gets the lease customer and contacts for an appraisal.

Parameters

testId: Int!

Response

result: LeaseUserDataModel

Example

query{
  testData_GetLeaseUserData(testId: 21) {
    customerId
    customerName
    fleetManagerName
    fleetManagerEmail
    installationRecipientEmail
    kamName
    kamEmail
    driverName
    driverPhone
    driverEmail
  }
}

Example response

{
  "data": {
    "testData_GetLeaseUserData": {
      "customerId": null,
      "customerName": null,
      "fleetManagerName": null,
      "fleetManagerEmail": null,
      "installationRecipientEmail": null,
      "kamName": null,
      "kamEmail": null,
      "driverName": null,
      "driverPhone": null,
      "driverEmail": null
    }
  }
}
Query Unit_GetAccessibleUnits Lists the units you have access to.

Response

result: [UnitModel]

Example

query{
  unit_GetAccessibleUnits
  {
    unitId
    unitName
  }
}

Example response

{
  "data": {
    "unit_GetAccessibleUnits": [
      {
        "unitId": 1,
        "unitName": "Test unit"
      }
    ]
  }
}
Query TestType_GetTestTypes Lists the appraisal types available for a unit.

Parameters

unitId: Int!
vin: String

Response

result: [TestTypeModel]

Example

query{
  testType_GetTestTypes(unitId: 1)
  {
    testTypeId,
    testTypeName,
    isActive
  }
}

Example response

{
  "data": {
    "testType_GetTestTypes": [
      {
        "testTypeId": 1,
        "testTypeName": "Test med kostnader",
        "isActive": true
      },
      {
        "testTypeId": 2,
        "testTypeName": "Test utan kostnader",
        "isActive": true
      },
      {
        "testTypeId": 3,
        "testTypeName": "Värdering av onormal slitage",
        "isActive": true
      },
      {
        "testTypeId": 770,
        "testTypeName": "Custom 1",
        "isActive": false
      }
    ]
  }
}
Mutation test_UpdateTest Updates an existing appraisal.

Parameters

testDataModel: TestDataModel!

Required

  • testDataModel.testId

Response

result: TestDataModel

Example

mutation {
  test_UpdateTest(testDataModel:  {
    testId: 625,
    mileage: 60000
  }) {
    testId,
    mileage
  }
}

Example response

SalesReport_CreateSalesReportFromSource
Query Test_GetAllTests A searchable, sortable list of all appraisals, with filters and paging.

Parameters

searchTerm: String
sortBy: GridSort
filters: TestFilterModel
skip: Int?
take: Int?
timeZoneOffset: Int?

Response

result: TestListModel

Notes

  • Results are paged with skip and take. take defaults to 50 and skip defaults to 0. There is no upper limit.
  • Sortable fields: regno, vehicleMake, vehicleModel, vin, completedDate, createdDate, performedDate, performedBy, testTypes, isObdPerformed, testStatus, testAnnotations.
  • searchTerm matches only when the text starts with RegNo or TestAnnotations.
  • timeZoneOffset is sent as minutes and is the difference between UTC time and client time (UTC − client time). If Swedish time is +1 GMT, send -1 to hit the right day.

Example

query {
  test_GetAllTests(searchTerm: "YSA053") {
            tests {
                testId
                regno
                vehicleMake
                vehicleModel
                vin
                createdDate
                performedDate
                completedDate
                performedBy
                testTypes
                isObdPerformed
                testStatus
                testAnnotations
                unitId
                unitName
            }
            totalTests
        }
    }
Query Test_GetActiveTests The same as above, but only appraisals in progress.

Parameters

searchTerm: String
sortBy: GridSort
filters: TestFilterModel
skip: Int?
take: Int?
timeZoneOffset: Int?

Response

result: TestListModel

Notes

  • Results are paged with skip and take. take defaults to 50 and skip defaults to 0. There is no upper limit.
  • Sortable fields: regno, vehicleMake, vehicleModel, vin, completedDate, createdDate, performedDate, performedBy, testTypes, isObdPerformed, testStatus, testAnnotations.
  • searchTerm matches only when the text starts with RegNo or TestAnnotations.
  • timeZoneOffset is sent as minutes and is the difference between UTC time and client time (UTC − client time). If Swedish time is +1 GMT, send -1 to hit the right day.

Example

query {
  test_GetActiveTests(searchTerm: "YSA053") {
            tests {
                testId
                regno
                vehicleMake
                vehicleModel
                vin
                createdDate
                performedDate
                completedDate
                performedBy
                testTypes
                isObdPerformed
                testStatus
                testAnnotations
                unitId
                unitName
            }
            totalTests
        }
    }
Query Test_GetTestReports Gets the links to the condition reports for an appraisal, including PDF.

Parameters

testId: Int!

Required

  • int testId

Response

result: [ReportModel]

Example

query {
        test_GetTestReports(testId: 33081) {
            testTypeId
            testType
            shortenedReportURL
            shortenedPdfReportURL
        }
    }

Example response

{
  "data": {
    "test_GetTestReports": [
      {
        "testTypeId": 2,
        "testType": "Test utan kostnader",
        "shortenedReportURL": "https://lnkt.bus.no/8049d5ll2"
        "shortenedPdfReportURL": "https://lnkt.bus.no/41181Ruhpp"
      }
    ]
  }
}
Query test_GetGeneralInfo Gets general information about the vehicle: keys, charging cable, previous use and more.

Parameters

testId: Int!

Response

result: GeneralInfoModel

Notes

  • Read the current values before updating. test_GetGeneralInfoMetaData provides the predefined key values.

Example

query {
  test_GetGeneralInfo(testId: 46324) {
    masterKeyCount
    chargingCableCount
    previousUseId
    hasPreviousDamage
    vehicleKeyTypes { key value }
    chargingCableTypes { key value }
  }
}

Example response

{ "data": { "test_GetGeneralInfo": { "masterKeyCount": 2, "chargingCableCount": 1, "previousUseId": 3, "hasPreviousDamage": false, "vehicleKeyTypes": [ { "key": 1, "value": "Remote key" } ], "chargingCableTypes": [] } } }
Mutation test_UpdateGeneralInfo Updates the general information about the vehicle.

Parameters

testId: Int!
generalInfoModel: GeneralInfoModel!

Response

result: Boolean

Notes

  • Read–modify–write: send the whole model. Null vehicleKeyTypes or chargingCableTypes lists are rejected; an empty list clears the existing types.

Example

mutation {
  test_UpdateGeneralInfo(testId: 46324, generalInfoModel: {
    masterKeyCount: 2,
    chargingCableCount: 1,
    previousUseId: 3,
    hasPreviousDamage: false,
    vehicleKeyTypes: [{ key: 1, value: "Remote key" }],
    chargingCableTypes: [{ key: 1, value: "Type 2" }]
  })
}

Example response

{ 
"data": 
    { 
        "test_UpdateGeneralInfo": true
    }
 }

Sales reports

Sales reports built on the appraisals, with share links and conclusion.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Production https://bus2.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Mutation SalesReport_CreateSalesReportFromSource Creates a sales report from an existing appraisal or a vehicle.

Parameters

regNo: String!
testRunId: Int?
unitId: Int?

Required

  • string regNo
  • int testRunId or int unitId

Response

result: Int

Example

mutation {
      salesReport_CreateSalesReportFromSource(regNo: "ØSXXR01", unitId: 5147)
  }

Example response

{
  "data": {
    "salesReport_CreateSalesReportFromSource": 764
  }
}
Query SalesReport_GetSalesReportShareMetaData Gets the share links for the sales report and the VDN report, and the PDF download.

Parameters

salesReportId: Int!

Required

  • int salesReportId

Notes

  • salesReportPdfDownloadSasUrl is available only to external partners.

Example

query {
  salesReport_GetSalesReportShareMetaData(salesReportId: 764) {
    shortenedSalesReportLinkURL
    shortenedVDNReportLinkURL
    shortenedSalesReportPdfURL
    salesReportPdfDownloadSasUrl
  }
}

Example response

{
  "data": {
    "salesReport_GetSalesReportShareMetaData": {
      "shortenedSalesReportLinkURL": "https://lnkt.bus.no/47430y13WA",
      "shortenedVDNReportLinkURL": "https://lnkt.bus.no/47431z3f1_",
      "shortenedSalesReportPdfURL": "https://lnkt.bus.no/47432iCS5k",
      "salesReportPdfDownloadSasUrl": "https://…/fil.jpg?sv=…&sig=…"
    }
  }
}
Query SalesReport_GetAllSalesReports A searchable, sortable list of all sales reports.

Parameters

searchTerm: String
sortBy: GridSort
filters: SalesReportFilterModel
skip: Int?
take: Int?
timeZoneOffset: Int?

Response

result: SalesReportListModel

Notes

  • Results are paged with skip and take. take defaults to 50 and skip defaults to 0. There is no upper limit.
  • Sortable fields: regno, vehicleMake, vehicleModel, vin, completedDate, salesReportStatus, createdDate, performedBy
  • searchTerm matches only when the text starts with RegNo.
  • timeZoneOffset is sent as minutes and is the difference between UTC time and client time (UTC − client time). If Swedish time is +1 GMT, send -1 to hit the right day.

Example

query {
  salesReport_GetAllSalesReports(searchTerm: "WBS99A") {
            salesReports {
                salesReportId
                salesReportStatus
                salesReportStatusId
                regno
                vehicleMake
                vehicleModel
                vin
                createdDate
                completedDate
            }
            totalSalesReports
        }
    }
Query SalesReport_GetActiveSalesReports The same as above, but only active sales reports.

Parameters

searchTerm: String
sortBy: GridSort
filters: SalesReportFilterModel
skip: Int?
take: Int?
timeZoneOffset: Int?

Response

result: SalesReportListModel

Notes

  • Results are paged with skip and take. take defaults to 50 and skip defaults to 0. There is no upper limit.
  • Sortable fields: regno, vehicleMake, vehicleModel, vin, completedDate, salesReportStatus, createdDate, performedBy
  • searchTerm matches only when the text starts with RegNo.
  • timeZoneOffset is sent as minutes and is the difference between UTC time and client time (UTC − client time). If Swedish time is +1 GMT, send -1 to hit the right day.

Example

query {
  salesReport_GetActiveSalesReports(searchTerm: "WBS99A") {
            salesReports {
                salesReportId
                salesReportStatus
                salesReportStatusId
                regno
                vehicleMake
                vehicleModel
                vin
                createdDate
                completedDate
            }
            totalSalesReports
        }
    }
Mutation SalesReport_UpdateSalesReport Updates a sales report.

Parameters

salesReportData: SalesReportDataModel!

Required

  • salesReportData.SalesReportId
  • salesReportData.TestId
  • salesReportData.UnitId

Response

result: SalesReportDataModel

Example

mutation UpdateSalesReport($salesReportData: SalesReportDataModelInput!) {
  updatedSalesReport: salesReport_UpdateSalesReport(
    salesReportData: $salesReportData
  ) {
    testId
    mileage
    createdDate
    completedDate
    salesReportTypeIds
    deviationNotes
    hasBatteryReading
    testStatusId
    unitId
    __typename
  }
}

Example response

{
  "data": {
    "updatedSalesReport": {
      "testId": 45068,
      "mileage": 12345,
      "createdDate": "2026-07-08T07:55:42.303Z",
      "completedDate": null,
      "salesReportTypeIds": [
        1,
        2,
        3
      ],
      "deviationNotes": null,
      "hasBatteryReading": false,
      "testStatusId": 8,
      "unitId": 5161,
      "__typename": "SalesReportDataModel"
    }
  }
}
Mutation salesReport_ConcludeSalesReport Concludes a sales report and sends it by email or SMS.

Parameters

salesReportConcludeModel: SalesReportConcludeModel!

Required

  • salesReportConcludeModel.salesReportId
  • salesReportConcludeModel.sendSalesReportEmailSMSModel

Response

result: Boolean

Notes

  • sendSalesReportEmailSMSModel is required, and the generated share links are stored on it. Empty email, number and report-type lists send nothing. Unit-configured recipients are appended at conclude. Open defects do not block conclusion.

Example

mutation {
  salesReport_ConcludeSalesReport(salesReportConcludeModel: {
    salesReportId: 3180,
    sendSalesReportEmailSMSModel: {
      salesReportId: 3180,
      emails: [],
      numbers: [],
      salesReportTypes: []
    }
  })
}

Example response

{ 
"data": 
           { 
                "salesReport_ConcludeSalesReport": true 
           }
 }
Mutation salesReport_AddSalesReportImages Adds images to a sales report, with an optional cover image.

Parameters

salesReportId: Int!
images: [SalesReportImageInputModel]!

Response

result: [SalesReportImageResultModel]

Example

mutation {
  salesReport_AddSalesReportImages (salesReportId: 3416,
  images: [ {
    isCover: false
    fileName: "354.jpg"
     url: "https://fastly.picsum.photos/id/471/536/354.jpg?hmac=ep1BMOqUf1L7RJA-pgAlrJFeXxAbxj7srUVwGoTiJGE"

  }])
  {
    fileName
    isSuccess
    reason
  }
}

Defects and damage

Defects and damage recorded on an appraisal, with images.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Production https://bus2.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Query Defect_GetTestDefects Gets the defects and damage recorded on an appraisal.

Parameters

testId: Int!

Response

result: [TestDefectModel]

Notes

  • TotalCost excludes VAT. A UI may display the amount including VAT.

Example

query{
  defect_GetTestDefects(testId: 54)
  {
    testDefectId,
    checkpoint {
      key
      value
    }
    checkpointComment {
      key
      value
    }
    commonCost,
    workCost,
    partsCost,
    totalCost
  }
}

Example response

{
  "data": {
    "defect_GetTestDefects": [
      {
        "testDefectId": 3444,
        "checkpoint": {
          "key": 2,
          "value": "Dokumentation utrustning - SW"
        },
        "checkpointComment": {
          "key": 9,
          "value": "testpunkten"
        },
        "commonCost": 100,
        "workCost": 60,
        "partsCost": 40,
        "totalCost": 200
      },
      {
        "checkpoint": {
          "key": 5,
          "value": "Registreringsskylt - SW"
        },
        "checkpointComment": {
          "key": 6,
          "value": "oläsbar"
        },
        "commonCost": 300,
        "workCost": 40,
        "partsCost": 30,
        "totalCost": 370
      }
    ]
  }
}
Query Defect_GetTestDefectFiles Gets the images and files attached to the defects on an appraisal.

Parameters

testId: Int!

Response

result: [TestDefectFileModel]

Example

query{
  defect_GetTestDefectFiles(testId: 54)
  {
    testDefectId,
    testDefectFiles
    {
      fileUrl,
      fileName,
      mediaId
    }
  }
}

Example response

{
  "data": {
    "defect_GetTestDefectFiles": [
      {
        "testDefectId": 320,
        "testDefectFiles": [
          {
            "fileUrl": https://dev.bus.no/busplatform3/RestAPIServers.FileServerCustom2/api/v1/File/GetFile?fileReference=CfDJ8EsheyHuiV5NuNJhGGxi8IXoncPhEgkimEBPt93Wv0WX_3ToA1zBeCaMvNsEJzD2-3CvE_hVeiyHpI4xg6ptP1jhDuKXHfBLQLcshyiaCEAJurCO5Grs5aCGN9RoQR38vX4jMsALbkHdcBWNhAaMKP1h7-I0l3pdRBmxOdrqYqdoQUyqExcUkS3z-vUsGTYqRH0 ,
            "fileName": "pexels_mike_bird_100653.jpg",
             "mediaId": "CD......"
          },
          {
            "fileUrl": https://dev.bus.no/busplatform3/RestAPIServers.FileServerCustom2/api/v1/File/GetFile?fileReference=CfDJ8EsheyHuiV5NuNJhGGxi8IVhMC9lQU7CYN_0177q1-fn1HgYQJnGAMqkLl9hBQurMaT4Ej6W45btBdwW0z-QEMIupfHvwSbixIiNJInMS4g4PmtVpvGw0MYIoH-hS_PRgcwUV6dEE1HmSFcNkydDbAKzgueyxbwBMMFnV6y0TG4tW2JGvK-fV1mvWQu7xdHaXx8 ,
            "fileName": "pexels_joshua_koller_757185.jpg",
            "mediaId": "CD......"
          }
        ]
      },
      {
        "testDefectId": 321,
        "testDefectFiles": []
      }
    ]
  }
}
Mutation Defect_UpdateTestDefect Updates a defect on an appraisal and on its sales report.

Parameters

testId: Int!
defectFormData: TestDefectModel!

Response

result: TestDefectModel

Example

mutation updateTestDefect($testId: Int!, $defectFormData: TestDefectModelInput!) {
  updatedDefect: defect_UpdateTestDefect(
    testId: $testId
    defectFormData: $defectFormData
  ) {
    testDefectId
    checkpointInstanceId
    checkpointGroup {
      key
      value
      __typename
    }
    checkpoint {
      key
      value
      __typename
    }
    checkpointComment {
      key
      value
      __typename
    }
    actionsList {
      actionId
      name
      __typename
    }
    positionsList {
      positionId
      name
      __typename
    }
    totalCost
    isTaxIncluded
    testDefectComment
    salesReportDefectId
    swedishStateReportLetterReferenceId
    stateGradeId
    __typename
  }
}

Example response

{
  "data": {
    "updatedDefect": {
      "testDefectId": 14276,
      "checkpointInstanceId": 285,
      "checkpointGroup": {
        "key": 1,
        "value": "Identifikation",
        "__typename": "KeyValueWithAdditionalItemOfNullableOfInt32"
      },
      "checkpoint": {
        "key": 59,
        "value": "Registreringsskylt",
        "__typename": "KeyValueModel"
      },
      "checkpointComment": {
        "key": 1,
        "value": "Skyltfäste",
        "__typename": "KeyValueModel"
      },
      "actionsList": [
        {
          "actionId": 6,
          "name": "Kontrollera",
          "__typename": "ActionModel"
        }
      ],
      "positionsList": [
        {
          "positionId": 2,
          "name": "Bak",
          "__typename": "PositionModel"
        }
      ],
      "totalCost": 66,
      "isTaxIncluded": true,
      "testDefectComment": "TEessserer",
      "salesReportDefectId": null,
      "swedishStateReportLetterReferenceId": null,
      "stateGradeId": 3,
      "__typename": "TestDefectModel"
    }
  }
}

Work orders

Work orders and jobs for the workshop flow.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Production https://bus2.bus.no/BUSPlatform3/BUSTest.Server/BUS.APIs.GraphQLServer.P3.BUSTest.ExternalEndpoint1
Mutation workOrder_CreateWorkOrder Creates a work order for a vehicle, with or without a linked appraisal.

Parameters

regNo: String!
testRunId: Int?!
unitId: Int!

Required

  • testRunId (optional for standalone work order)

Response

result: Int

Notes

  • With testRunId the test must be concluded, and one job is created per defect. Without testRunId a standalone work order is created.

Example

mutation {
  workOrder_CreateWorkOrder(regNo: "PHP526", testRunId: 45988, unitId: 5147)
}

Example response

{ 
"data": 
     {
          "workOrder_CreateWorkOrder": 1773
     }
 }
Mutation workOrder_CreateWorkOrderJob Adds a job to a work order.

Parameters

workOrderJobModel: WorkOrderJobModel!

Required

  • workOrderJobModel (workOrderId and job details)

Response

result: WorkOrderJobModel

Example

mutation {
  workOrder_CreateWorkOrderJob(workOrderJobModel: {
    workOrderId: 1773,
    jobName: "Replace wiper blades",
    comment: "Added by partner"
  }) {
    workOrderJobId
    jobName
  }
}

Example response

{ 
"data":
         { "workOrder_CreateWorkOrderJob": { 
                           "workOrderJobId": 28584, "jobName": "Replace wiper blades"
                   }
          }
 }
Mutation workOrder_AddStandardJobsToWorkOrderCycle Adds standard jobs to a work order.

Parameters

workOrderId: Int!
standardJobIds: [Int]!

Response

result: [WorkOrderJobModel]

Example

mutation {
  workOrder_AddStandardJobsToWorkOrderCycle(workOrderId: 1773, standardJobIds: [101, 205]) {
    workOrderJobId
    jobName
  }
}

Example response

{ 
"data": 
            { "workOrder_AddStandardJobsToWorkOrderCycle":
                            [ { "workOrderJobId": 28585, "jobName": "Standard service" } ] 
            }
 }
Query workOrder_GetWorkOrderJobList Gets all the jobs on a work order.

Parameters

workOrderId: Int!

Response

result: WorkOrderJobListModel

Notes

  • workOrderJobStatus is a nested object. Use the job identities returned here when setting status.

Example

query {
  workOrder_GetWorkOrderJobList(workOrderId: 1773) {
    count
    workOrderJobs {
      workOrderJobId
      jobName
      workOrderJobStatus {
        workOrderJobStatusId
        workOrderJobStatusName
      }
      testDefect {
        testDefectId
      }
    }
  }
}

Example response

{ 
"data":
                { "workOrder_GetWorkOrderJobList":
                                              { "count": 2, "workOrderJobs": [ 
                                                                  { "workOrderJobId": 28581, "jobName": "Defect job", "workOrderJobStatus": { "workOrderJobStatusId": 3,                             "workOrderJobStatusName": "Done" }, "testDefect": { "testDefectId": 3444 } } 
                                                             ]
                                                }
                  }
 }
Mutation workOrder_UpdateWorkOrderJobStatus Sets a new status on one or more jobs.

Parameters

workOrderId: Int!
workOrderJobIds: [Int]!
workOrderJobStatusId: Int!

Response

result: WorkOrderStatusUpdateResult

Notes

  • Done appears as fixed on the sales report, Open as still a defect. The work order status is kept in sync.

Example

mutation {
  workOrder_UpdateWorkOrderJobStatus(
    workOrderId: 1773,
    workOrderJobIds: [28581, 28582],
    workOrderJobStatusId: 3
  ) {
    workOrderStatusId
    workOrderStatusName
    updatedJobs {
      workOrderJobId
      workOrderJobStatusId
      workOrderJobStatusName
    }
  }
}

Example response

{ "data": { "workOrder_UpdateWorkOrderJobStatus": { "workOrderStatusId": 2, "workOrderStatusName": "InProgress", "updatedJobs": [ { "workOrderJobId": 28581, "workOrderJobStatusId": 3, "workOrderJobStatusName": "Done" } ] } } }
Query workOrder_GetStandardJobsForWorkOrder Lists the standard jobs that can be attached to a work order.

Parameters

workOrderId: Int!

Response

result: [StandardJobModel]

Example

query{
  workOrder_GetStandardJobsForWorkOrder(
    workOrderId: 1832)
  {
    standardJobId
    jobName
    cost
    isTaxInclude
  }
}

Example response

{
  "data": {
    "workOrder_GetStandardJobsForWorkOrder": [
      {
        "standardJobId": 723,
        "jobName": "Shenal standard - job",
        "cost": 800,
        "isTaxInclude": false
      }
    ]
  }
}
Query workOrderSettings_GetStandardJobsListForUnit Lists the unit's own standard jobs with cost.

Parameters

unitId: Int!

Response

result: StandardJobsGridModel

Example

query{
  workOrderSettings_GetStandardJobsListForUnit(unitId: 5208)
  {
    totalStandardJobs
    standardJobs {
      standardJobId
      jobName
      cost
    }
  }
}

Example response

{
  "data": {
    "workOrderSettings_GetStandardJobsListForUnit": {
      "totalStandardJobs": 6,
      "standardJobs": [
        {
          "standardJobId": 775,
          "jobName": "DT",
          "cost": 434
        },
        {
          "standardJobId": 737,
          "jobName": "Group 2 only LT",
          "cost": 0
        },
        {
          "standardJobId": 736,
          "jobName": "Group 1,2 only LT",
          "cost": 0
        },
        {
          "standardJobId": 734,
          "jobName": "Group 2 only CT",
          "cost": 0
        },
        {
          "standardJobId": 732,
          "jobName": "Group 1,2 CT",
          "cost": 0
        },
        {
          "standardJobId": 456,
          "jobName": "Group 1,2,3",
          "cost": 0
        }
      ]
    }
  }
}
Query workOrder_GetTestRunsForWorkOrderCreation Lists the test runs eligible to become a work order for a registration number.

Parameters

regNo: String!
unitId: Int!

Example

query{
  workOrder_GetTestRunsForWorkOrderCreation(
    regNo: "AOL449"
    , unitId: 5147
    )
  {
    isRegNoValid
    items {
      testId
      testRunId
      mileage
    }
  }
}

Example response

{
  "data": {
    "workOrder_GetTestRunsForWorkOrderCreation": {
      "isRegNoValid": true,
      "items": [
        {
          "testId": 3456,
          "testRunId": 46664,
          "mileage": 45000
        },
        {
          "testId": 3457,
          "testRunId": 46663,
          "mileage": 45000
        },
        {
          "testId": 3458,
          "testRunId": 39591,
          "mileage": 45000
        },
        {
          "testId": 3459,
          "testRunId": 41191,
          "mileage": 45000
        },
        {
          "testId": 3460,
          "testRunId": 41223,
          "mileage": 66666
        },
        {
          "testId": 3461,
          "testRunId": 2358,
          "mileage": 100001
        },
        {
          "testId": 3462,
          "testRunId": 39356,
          "mileage": 1500
        },
        {
          "testId": 3463,
          "testRunId": 39363,
          "mileage": 33000
        },
        {
          "testId": 3464,
          "testRunId": 39264,
          "mileage": 45009
        },
        {
          "testId": 3465,
          "testRunId": 2887,
          "mileage": 222222
        }
      ]
    }
  }
}
Query workOrder_GetAllWorkOrders Lists all work orders. Searchable, sortable and paged.

Parameters

searchTerm: String
sortBy: GridSort
filters: WorkOrderFilterModel
skip: Int?
take: Int?
timeZoneOffset: Int

Response

result: WorkOrderListModel

Notes

  • Results are paged with skip and take. take defaults to 50 and skip defaults to 0. There is no upper limit.
  • timeZoneOffset is sent as minutes and is the difference between UTC time and client time (UTC − client time). If Swedish time is +1 GMT, send -1 to hit the right day.

Example

query{
  workOrder_GetAllWorkOrders(
    searchTerm: "AOL449"
    timeZoneOffset: 0
    )
    {
      totalWorkOrders
      workOrders
      {
        testId
        workOrderId
        vehicleMake
        vehicleModel
      }
    }
  }
}

Example response

{
  "data": {
    "workOrder_GetAllWorkOrders": {
      "totalWorkOrders": 8,
      "workOrders": [
        {
          "testId": 47186,
          "workOrderId": 1832,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 45523,
          "workOrderId": 1698,
          "vehicleMake": "",
          "vehicleModel": ""
        },
        {
          "testId": 41141,
          "workOrderId": 1419,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 40793,
          "workOrderId": 1376,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 40709,
          "workOrderId": 1362,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 38984,
          "workOrderId": 1016,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 38976,
          "workOrderId": 1015,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 38904,
          "workOrderId": 994,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        }
      ]
    }
  }
}
Query workOrder_GetActiveWorkOrders Lists work orders that are not concluded.

Parameters

searchTerm: String
sortBy: GridSort
filters: WorkOrderFilterModel
skip: Int?
take: Int?
timeZoneOffset: Int

Response

result: WorkOrderListModel

Notes

  • Results are paged with skip and take. take defaults to 50 and skip defaults to 0. There is no upper limit.
  • timeZoneOffset is sent as minutes and is the difference between UTC time and client time (UTC − client time). If Swedish time is +1 GMT, send -1 to hit the right day.

Example

query{
  workOrder_GetActiveWorkOrders(
    searchTerm: "AOL449"
    timeZoneOffset: 0
    )
    {
      totalWorkOrders
      workOrders
      {
        testId
        workOrderId
        vehicleMake
        vehicleModel
      }
    }
  }
}

Example response

{
  "data": {
    "workOrder_GetActiveWorkOrders": {
      "totalWorkOrders": 7,
      "workOrders": [
        {
          "testId": 47186,
          "workOrderId": 1832,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 45523,
          "workOrderId": 1698,
          "vehicleMake": "",
          "vehicleModel": ""
        },
        {
          "testId": 41141,
          "workOrderId": 1419,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 40793,
          "workOrderId": 1376,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 40709,
          "workOrderId": 1362,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 38984,
          "workOrderId": 1016,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        },
        {
          "testId": 38904,
          "workOrderId": 994,
          "vehicleMake": "Ford",
          "vehicleModel": "Transit Connect 230 LWB"
        }
      ]
    }
  }
}
Mutation workOrder_ConcludeWorkOrder Concludes a work order.

Parameters

workOrderId: Int!

Response

result: Boolean

Example

mutation{
  workOrder_ConcludeWorkOrder(workOrderId: 1832)
}

Example response

{
  "data": {
    "workOrder_ConcludeWorkOrder": true
  }
}
Mutation workOrder_ReopenWorkOrder Reopens a concluded work order.

Parameters

workOrderId: Int!

Response

result: Boolean

Example

mutation{
  workOrder_ReopenWorkOrder(workOrderId: 1832)
}

Example response

{
  "data": {
    "workOrder_ReopenWorkOrder": true
  }
}
Mutation workOrder_DeleteWorkOrder Deletes a work order.

Parameters

workOrderId: Int!

Response

result: Boolean

Example

mutation{
  workOrder_DeleteWorkOrder(workOrderId: 1824)
}

Example response

{
  "data": {
    "workOrder_DeleteWorkOrder": true
  }
}
Query workOrder_GetWorkOrder Retrieves a single work order.

Parameters

workOrderId: Int!

Response

result: WorkOrderDataModel

Example

query{
  workOrder_GetWorkOrder(workOrderId: 1832)
  {
    workOrderId
    regNo
    mileage
    workOrderStatusId
  }
}

Example response

{
  "data": {
    "workOrder_GetWorkOrder": {
      "workOrderId": 1832,
      "regNo": "AOL449",
      "mileage": 45000,
      "workOrderStatusId": 5
    }
  }
}

Files

REST endpoints for fetching images and documents.

The sandbox requires sign-in. Contact us for test credentials.

API type REST
Staging https://test.bus.no/BUSPlatform3/RestAPIServers.FileServer/api
Production https://bus2.bus.no/busplatform3/RestAPIServers.FileServer/api
REST Media/GetMedia Gets the file itself from a media id. With useRedirect the file is fetched straight from storage, which is fastest.

Parameters

mediaId: String!
useRedirect: Boolean

Response

Actual file

Example

curl -X 'GET' \
  'https://test.bus.no/BUSPlatform3/RestAPIServers.FileServer/api/Media/GetMedia?api-version=1&mediaId=xxxx' \
  -H 'accept: */*' \
  -H 'x-api-version: 1' \
  -H 'x-access-token: eyJhb...'
REST Media/GetMediaSas Gets a temporary download link (SAS) for a media id, with its expiry time.

Parameters

mediaId: String!

Response

sasUrl expiresOn

Example

curl -X 'GET' \
  'https://test.bus.no/BUSPlatform3/RestAPIServers.FileServer/api/Media/GetMediaSas?api-version=1&mediaId=xxxx' \
  -H 'accept: application/json' \
  -H 'x-api-version: 1' \
  -H 'x-access-token: eyJhb...'

Real-time

Subscribe to real-time events when an appraisal is concluded.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging wss://test.bus.no/BUSPlatform3/MessagingPortal/BUS.APIs.GraphQLServer.P3.MessagingPortal.ExternalEndpoint1
Production wss://bus2.bus.no/BUSPlatform3/MessagingPortal/BUS.APIs.GraphQLServer.P3.MessagingPortal.ExternalEndpoint1
Subscription Test_OnTestConclude Tells you in real time when an appraisal has been concluded.

Parameters

testId: Int!

Response

result: TestDataModel

Notes

  • Localized text fields such as testStatus and checkpoint names are returned in the caller's culture. The culture is taken from the token's culture claim, falling back to Accept-Language. The example was captured with Swedish culture.

Example

subscription{
  test_OnTestConclude(testId: 54)
  {
    testId,
    mileage,
    serviceData {
      date,
      mileage,
      comment
    },
    unitId,
    testTypeIds,
    testStatus
  }
}

Example response

{
  "data": {
    "test_GetTest": {
      "testId": 54,
      "mileage": 45000,
      "serviceData": [
        {
          "date": "2022-04-04T18:30:00.000Z",
          "mileage": 2000,
          "comment": null
        },
        {
          "date": "2023-06-22T18:30:00.000Z",
          "mileage": 10000,
          "comment": null
        }
      ],
      "unitId": 1,
      "testTypeIds": [
        2
      ],
      "testStatus": "Test färdigställd"
    }
  }
}

Webhooks

Register a webhook and receive events on your own URL. B.U.S. sends one JSON POST per event, and accepts any 2xx as acknowledgement.

The sandbox requires sign-in. Contact us for test credentials.

API type GraphQL
Staging https://test.bus.no/BUSPlatform3/MessagingPortal/BUS.APIs.GraphQLServer.P3.MessagingPortal.InternalApp
Production https://bus2.bus.no/BUSPlatform3/MessagingPortal/BUS.APIs.GraphQLServer.P3.MessagingPortal.InternalApp
Mutation notification_SubscribeWebhook Registers a webhook, generally or for one unit. Returns a secret that B.U.S. includes in every notification payload, so you can confirm the notification came from us.

Parameters

webhookRegisterModel: WebhookRegisterModel (url, eventTypeId, unitId?)

Required

  • url
  • eventTypeId

Response

secret: String

Notes

  • Each delivery is one JSON POST. A 2xx means delivered; any other response is logged as a failure and is not retried.

Example

mutation{
  notification_SubscribeWebhook(webhookRegisterModel:  {
    url: "https://example.com/webhook",
    eventTypeId: 1,
    unitId: null
  }
  ){
    secret
  }
}

Example response

{
  "data": {
    "notification_SubscribeWebhook": {
      "secret": "…"
    }
  }
}
Mutation notification_UnsubscribeWebhook Removes a registered webhook.

Parameters

eventTypeId: Int!
unitId: Int?

Response

result: Boolean

Example

mutation{
  notification_UnsubscribeWebhook(eventTypeId:  1, unitId: 5147)
}
Webhook TestConcluded The notification B.U.S. sends to your webhook when an appraisal has been concluded.

Response

EventName, Data (TestDataModel), Secret

Notes

  • Each delivery is one JSON POST. A 2xx means delivered; any other response is logged as a failure and is not retried.

Example

{
  "EventName": "TestConcluded",
  "Data": { "TestId": 34626, "UnitId": 5147, "Mileage": 3234, "…": "…" },
  "Secret": "…"
}
Webhook TestDeleted The notification B.U.S. sends to your webhook when an appraisal is deleted.

Response

EventName, Data (TestDataModel), Secret

Notes

  • Each delivery is one JSON POST. A 2xx means delivered; any other response is logged as a failure and is not retried.

Example

{
  "EventName": "TestDeleted",
  "Data": {
    "TestId": 34626,
    "TestRunId": 34927,
    "UnitId": 5147,
    "UnitName": null,
    "Mileage": 3234,
    "ExpectedArrivalDate": null,
    "ExpectedArrivalKM": null,
    "RequestedCompletionDate": null,
    "ParkingLocation": null,
    "KeyLocation": null,
    "IsMVASelected": false,
    "TestStatus": "Test: Klar",
    "PerformedUserId": null,
    "PerformedBy": "",
    "PerformedDate": "2025-10-24T09:36:46.217Z",
    "TestTypeIds": [
      2133
    ],
    "IsPublic": false,
    "TestTypeEmails": null,
    "TestTypeDescription": null,
    "ServiceData": [],
    "TestPersonId": 163,
    "TestComments": [],
    "TestOrderedBy": null,
    "TestCoverImage": null,
    "ExternalReferenceId": null,
    "TestAnnotations": [],
    "TestStatusId": 3,
    "IsDeleted": false,
    "CreatedDate": "2025-10-24T09:36:46.217Z",
    "HasValidBatteryReading": null,
    "IsValidTestDrive": null,
    "IsTestTypeVersionUpdated": null,
    "LastUpdatedeDate": "2025-10-24T09:36:46.217Z",
    "CompletedDate": "2025-10-24T09:39:37.877Z",
    "TestDefects": null
  },
  "Secret": null
}
Webhook WorkOrderConcluded The notification B.U.S. sends to your webhook when a work order is concluded.

Response

EventName, Data (WorkOrderDataModel), Secret

Notes

  • Each delivery is one JSON POST. A 2xx means delivered; any other response is logged as a failure and is not retried.

Example

{
  "EventName": "WorkOrderConcluded",
  "Data": {
    "WorkOrderId": 1832,
    "TestId": 47186,
    "TestRunId": 46664,
    "UnitId": 5147,
    "IsShared": false,
    "Mileage": 45000,
    "JobsStartDate": null,
    "JobsCompletionDate": null,
    "WorkOrderStatusId": 6,
    "IsDeleted": false,
    "RegNo": "AOL449",
    "IsSalesReportCreated": true,
    "CreatedSalesReportId": 3416,
    "IsCreatedFromTest": true,
    "HasAllAccess": false
  },
  "Secret": null
}

Data models

The types used in parameters and responses.

TestDataModel
UnitId: Int?
Mileage: Int?
ParkingLocation: String?
KeyLocation: String
TestStatus: String
TestTypeIds: [Int]
ServiceData: [ServiceMileageModel]
TestComments: [String]
ExternalReferenceId: String
TestAnnotations: [String]
testOrderedBy: String
VehicleDataModel
RegNo: String
Vin: String
VehicleType: String
TrimLevel: String
VehicleOptions: [VehicleOptionModel]
VehiclePackages: [VehiclePackageModel]
Color: String
Model: String
Make: String
GearBox: String
Engine: String
ManufacturedYear: Int?
ManufacturedMonth: Int?
Co2Emissions: Decimal?
ServiceMileageModel
Date: DateTime?
Mileage: Int?
Comment: String?
TestDefectModel
TestDefectId: Int
Checkpoint: KeyValueModel
CheckpointComment: KeyValueModel
CommonCost: Decimal
WorkCost: Decimal
PartsCost: Decimal
TotalCost: Decimal
TestTypeModel
TestTypeId: Int
TestTypeName: String
TestFileModel
FileUrl: String
FileName: String
FileReference: String
mediaId: String
testSectionId: Int
TestDefectFileModel
TestDefectFiles: [TestFileModel]
TestDefectId: Int
KeyValueModel
Key: Int
Value: String
VehicleOptionModel
OptionName: String
IncludedItems: String
IsSelected: Boolean?
VehiclePackageModel
PackageName: String
VehicleOptions: [VehicleOptionModel]
IsSelected: Boolean?
LeaseDataModel
PurchasePrice: Decimal?
ProductType: String
RepairMaintenance: String
WinterTires: String
TransportDate: DateTime?
QuotationTemplate: String
LeaseUserDataModel
CustomerId: String
CustomerName: String
FleetManagerName: String
FleetManagerEmail: String
InstallationRecipientEmail: String
KamName: String
KamEmail: String
DriverName: String
DriverPhone: String
DriverEmail: String
UnitModel
unitId: Int
unitName: String
TestListModel
tests: [TestGridInformationModel]
totalTests: Int
TestGridInformationModel
TestId: Int?
TestStatus: String
Regno: String
VehicleMake: String
VehicleModel: String
Vin: String
TestTypes: String
TestPersonId: Int?
IsActiveTest: Boolean
IsTestConcluded: Boolean
IsObdPerformed: Boolean
PerformedBy: String
PerformedDate: DateTime?
CreatedDate: DateTime
CompletedDate: DateTime?
TestAnnotations: String
GridSort
Field: String
Dir: SortDirection
SortDirection
enum SortDirection{
Asc
Desc
}
TestFilterModel
OrderedBy: [KeyValueModel]
TestDate: KeyValueModel
TestType: [KeyValueModel]
Status: [KeyValueModel]
CompletedDate: KeyValueModel
ReportModel
TestTypeId: Int
TestType: String
ReportURL: String
ShortenedReportURL: String
ShortenedPdfReportURL: String
DownloadUrl: String
SalesReportShareMetaDataModel
ShortenedSalesReportLinkURL: String
ShortenedVDNReportLinkURL: String
ShortenedSalesReportPdfURL: String
SalesReportPdfDownloadSasUrl: String
SalesReportFilterModel
CompletedDate: KeyValueModel
Status: [KeyValueModel]
PerformedBy: [KeyValueModel]
CreatedDate: KeyValueModel
WorkOrderFilterModel
CreatedDate: KeyValueModel
CompletedDate: KeyValueModel
SharedStatus: KeyValueModel
Status: [KeyValueModel]
WorkOrderUnit: [KeyValueModel]
Unit: [Int]
SalesReportListModel
SalesReports: [SalesReportGridInformationModel]
TotalSalesReports: Int
SalesReportGridInformationModel
SalesReportId: Int
SalesReportStatus: String
SalesReportStatusId: Int?
Regno: String
VehicleMake: String
VehicleModel: String
Vin: String
CreatedDate: DateTime
CompletedDate: DateTime?
WorkOrderJobModel
WorkOrderJobId
WorkOrderId
WorkOrderJobTypeId
JobName
WorkOrderJobStatus: WorkOrderJobStatusModel
IsShared
IsSentToSupplier
ExternalCost
RepairCost
Supplier
TestDefect
Comment
StandardJob
StartDate
CompletionDate
WorkOrderJobListModel
Count
WorkOrderJobs: [WorkOrderJobModel]
WorkOrderStatusUpdateResult
WorkOrderStatusId
WorkOrderStatusName
UpdatedJobs: [WorkOrderJobStatusModel]
WorkOrderJobStatusModel
WorkOrderJobId
WorkOrderJobStatusId
IsSentToSupplier
WorkOrderJobStatusName
GeneralInfoModel
MasterKeyCount
ChargingCableCount
PreviousUseId
HasPreviousDamage
IsLuggageCoverAvailable
IsTemperatureMeasured
TemperatureInside
TemperatureOutside
ACTestSkipReasonId
LocknutsAvailabilityStatusId
NextServiceDate
VehicleKeyTypes
ChargingCableTypes
SalesReportConcludeModel
SendSalesReportEmailSMSModel
SalesReportId
SalesReportTypes
Emails
Numbers
Description
ShortenedSalesReportLinkURL
ShortenedVDNReportLinkURL
ShortenedSalesReportPdfURL
SalesReportPdfDownloadSasUrl
StandardJobModel
StandardJobId: Int
StandardJobStatusId: Int
ParentStandardJobId: Int?
JobName: String
Cost: Decimal?
IsTaxInclude: Boolean
IsIncludedInCycle: Boolean
SupplierName: String
WorkOrderCreationTestRunListModel
WorkOrderCreationTestRunModel
TestId: Int?
TestRunId: Int
WorkOrderId: Int?
TestTypeNames: [String]
TestRunStatuses: TestRunStatusesModel
Mileage: Int
Date: DateTime
UnitName: String
TestRunStatusesModel
TestStatus: KeyValuePair<Int, String>?
WorkOrderStatus: KeyValuePair<Int, String>?
SalesReportStatus: KeyValuePair<Int, String>?
PreTestStatus: KeyValuePair<Int, String>?
WorkOrderListModel
WorkOrders: [WorkOrderGridInformationModel]
TotalWorkOrders: Int
WorkOrderGridInformationModel
TestId: Int
WorkOrderId: Int
WorkOrderStatus: String
Regno: String
VehicleMake: String
VehicleModel: String
Vin: String
CreatedDate: DateTime
CompletedDate: DateTime?
UnitId: Int
UnitName: String
SalesReportImageResultModel
FileName: String
IsSuccess: Boolean
Reason: String
AttachmentOrder: Int?
SalesReportImageInputModel
Url: String
FileName: String
IsCover: Boolean
WorkOrderDataModel
WorkOrderId: Int
TestId: Int
TestRunId: Int?
UnitId: Int
Mileage: Int?
JobsStartDate: DateTime?
JobsCompletionDate: DateTime?
WorkOrderStatusId: Int?
RegNo: String?
StandardJobsGridModel
StandardJobs: [StandardJobModel]
TotalStandardJobs: Int

The B.U.S. Shop

Built an integration that’s useful for workshops or dealers? Make it available in the B.U.S. Shop, the marketplace where B.U.S. customers find and activate integrations. Your integration reaches three out of four workshops in Norway, without your own sales organisation.

Technical

AuthenticationBearer token. Sandbox credentials on request, production after approval.
FormatGraphQL.
Rate limitsUnlimited in sandbox. No fixed limit in production today. Misuse can lead to the account being blocked, and the service can answer with 429 (Too Many Requests).
WebhooksReal-time events. New inspection, updated appraisal, status change. Choose which events you subscribe to.
ChangesWe do not introduce breaking changes. New needs are covered by new methods, and existing methods and fields are not changed while they are in use. New methods and optional fields can be added over time. Changes are announced by email to the technical contact.
SchemaIntrospection is on. You can fetch the whole schema with the introspection query against the endpoint, or read it in the GraphQL sandbox. Each API has its own schema - the Test API and Oscar Inspector are separate endpoints. The schema is generated at build time, so it always matches the service.

FAQ

Which languages/SDKs are supported?

GraphQL-based. Works with any language that can send HTTP requests. Choose which fields you want back.

What does it cost?

Sandbox is free. Pricing for production access depends on usage.

Ready to build?

Explore the API catalogue, or talk to a developer at B.U.S.