NAV Navigation
Examples

Overview

This site provides a high level overview of our APIs.

Reference documentation is available here:

stock
webhooks

Auctions

Currently, we support three types of transactional listing, Buy Now, Online Auction and Sealed Bid.

We also support a legacy Physical Auction channel.

Buy Now

Buy now listings are the simplest. The listing has a single price and can be bought immediately.

Online Auction

Online Auction listings run for a set period. When this time period has elapsed, if there is at least one bid that is greater or equal to reserve price, then the listing has sold. If not, then the listing has expired.

Highest bidder wins.

Auctions can have an optional start price which sets the initial price of the listing if there are no bids.

Auctions can also have a “buy now price”. If a bid arrives that is equal to the buy now price, then the auction immediately finishes.

Auctions will end up in one of three states, SOLD EXPIRED or CANCELLED. The seller will be sent an email when their auction reaches one of these states.

Bidders will also be emailed when the auction reaches one of these three final states.

Notes on modifying a running auction

Running auctions cannot be modified. If you attempt to make changes to it via the stock API, the request will be rejected. To modify properties of an auction (reserve price, starting price etc) then you must first cancel the auction that is running. The auction can then be modified and started again.

Cancelled auctions

When an auction is cancelled, any bidders will be notified. If the auction is relisted, their previous bids do not count. The bidders will have to make new bids if they wish to participate. For this reason, think carefully and try to ensure your auction is correct before starting it.

Sealed Bid

Sealed bid listings are very similar to the standard auction.

Mostly they differ in how they’re presented to the user. A sealed bid listing has a fixed display price whereas an online auction has a running price that increases with each bid.

A sealed bid auction does not need to have a reserve price. If no reserve is specified then the vehicle will need to be negotiated before it can sell.

Sealed bids can also have a buy now price.

Stock

Reference documentation

Creating stock

Request Body - with only mandatory fields

{
"customerId": "1234",
"metadata": {
"externalStockId": null,
"externalVendorId": null
},
"vehicle": {
"vrm": "REG1234",
"make": "Nissan",
"model": "Micra",
"category": "Car",
"ownershipCondition": "USED",
"stolen": false,
"imported": false,
"exported": false,
"scrapped": false
},
"features": [],
"images": []
}

Very few fields are actually required to create a vehicle on our platform.

However, more fields will be required before the vehicle can be listed.

Updating stock

Partial update that activates an advert

{
"advert": {
"state": "ACTIVE"
}
}

Partial update that de-activates an advert

{
"advert": {
"state": "INACTIVE"
}
}

Partial update that changes the vehicle key count

{
"vehicle": {
"keys": 2
}
}

Deeply nested values can be updated

{
"advert": {
"buyNowPrice": {
"value": 13800
}
}
}

Updates are supported via PATCH requests. You can either PATCH the full document or just the fields that you wish to change. Using a blank string or a null value will try and set the field value to blank or null respectively. Not changing a field can only be done by not sending it in the patch request.

Multiple fields can be changed at once, as can individual fields within a nested block.

The GET response includes additional fields that are not considered when creating or updating. But it is fine to include these fields, they will simply be ignored.

Date times and time zones

For a datetime field to be considered valid, a time zone must be included.

We recommend you always supply datetimes in UTC format (trailing Z). This will help ensure there are no auction scheduling issues that could occur due to variable time zones (daylight saving time).

Both below formats are acceptable; however, we prefer the UTC version.

UTC datetime: 2020-11-10T13:00:11Z
ISO datetime: 2020-11-10T13:00:11+01:00

If you fail to specify a time zone, your request will be rejected. This datetime will fail: 2020-11-10T11:59:11

Datetime values in HTTP responses will always be returned as UTC format.

Activating and deactivating an advert

You can patch the advert state field to ACTIVE or INACTIVE to control whether an advert is active.

This will cause an auction or buy now to be created. We will set the start and end times for you.

If you want to control the end time for a listing then this can be achieved by setting startDate and endDate on the auction block of the advert.

We recommend not setting end times for auctions. Instead, provide an availableUntil value to ensure that stock only sits with us for a certain period of time.

Legacy advert start and end dates

The advert startDate and endDate fields are now deprecated. Previously, these fields were used both to control advert state and also auction duration. This choice kept things simple but a little brittle. Some stock providers want to activate listings without specifying auction length.

Advert start and end dates will continue to work for now, however they are deprecated.

If you provide legacy advert start and end dates but also provide advert state then the advert dates will take priority. For example, if you specify a state of ACTIVE but your endDate is in the past, the advert will not be activated.

Error responses

validation error response

{
"errors": [
{
"message": "The vehicle registration cannot be in the future"
}
],
"errorCode": "INVALID_STOCK_ITEM"
}

stock rejected error response

{
"errors": [
{
"message": "Rejected due to invalid make: SKODAA"
},
{
"message": "Rejected due to invalid model: Karoq"
}
],
"errorCode": "STOCK_REJECTED"
}

running auction modification error response

{
"errorCode": "STOCK_CANNOT_BE_MODIFIED_WHILE_AUCTION_IS_RUNNING"
}

stock creation error response

{
"errorCode": "STOCK_ALREADY_EXISTS"
}

Stock modification may fail for several reasons

Forbidden stock

You have attempted to fetch or modify stock that is not associated to one of your customer accounts.

403 forbidden HTTP response code.

Not found

Stock could not be found. You’ve tried to get or modify a stock item that does not exist.

404 not found HTTP response code.

Validation error

Stock has failed one or more validation checks. This is covered in more detail in the next section.

Includes an error response body.

400 bad request HTTP response code.

Stock rejection error

There is invalid information relating to the vehicle. For example, a bad make or model.

Includes an error response body.

400 bad request HTTP response code.

Running auction modification error

You cannot modify a stock item if it is for a BID auction that is currently running. This is to prevent people adding additional information / changing prices once bids have been made.

To modify the auction, the advert must be expired. Then changes can be made, and a new auction must then be started by adjusting the advert end date again.

Includes an error response body.

400 bad request HTTP response code.

Stock already exists error

If you attempt to create a vehicle that we believe already exists against your customer account, then we will reject the stock item.

We will include the VRM of the vehicle that we believe already exists. You should then search for the stock item using this VRM.

Includes an error response body.

409 conflict HTTP response code.

Stock validation rules

Prior to stock being created or updated, it will be run through a series of validation checks.

Validation rules

You cannot save more than 200 features.

Condition reports must be in pdf format

Date of registration cannot be in the future

Only Car, Van and Bike vehicle types are acceptable

Auction validation

BUY_NOW auctions must have a buy now price

BID auctions can have a buy now price, but it must be greater than the reserve price (if there is a reserve price)

As already mentioned, BID auctions cannot be modified in any way while their advert is active. Attempts to do so will be met with a STOCK_CANNOT_BE_MODIFIED_WHILE_AUCTION_IS_RUNNING error.

Damage chart

Example damage items

{
"condition": {
"damageItems": [
{
"zone": "BUMPER_REAR",
"damageType": "CHIP"
},
{
"zone": "ROOF",
"damageType": "CRACK"
}
]
}
}

Damage charts can be generated by submitting a list of damage types and zones.

Below is a picture of our damage chart. Hovering over zones will highlight them and display their names.

Selected region

...

Copied to clipboard!

Exterior regions

(Click an item below to copy it to your clipboard)

  • WINDSCREEN
  • WINDSCREEN_REAR
  • BOOTLID
  • ROOF
  • BONNET
  • MIRROR_COVER_NEAR_SIDE
  • MIRROR_COVER_FAR_SIDE
  • DOOR_FRONT_FAR_SIDE
  • DOOR_FRONT_NEAR_SIDE
  • DOOR_REAR_FAR_SIDE
  • DOOR_REAR_NEAR_SIDE
  • WING_FRONT_NEAR_SIDE
  • WING_FRONT_FAR_SIDE
  • WING_REAR_FAR_SIDE
  • WING_REAR_NEAR_SIDE
  • WHEELS_FRONT_NEAR_SIDE
  • WHEELS_FRONT_FAR_SIDE
  • WHEELS_REAR_NEAR_SIDE
  • WHEELS_REAR_FAR_SIDE
  • BUMPER_FRONT
  • BUMPER_REAR
  • NUMBER_PLATE_FRONT
  • NUMBER_PLATE_REAR
  • WINDOW_FRONT_NEAR_SIDE
  • WINDOW_FRONT_FAR_SIDE
  • WINDOW_REAR_NEAR_SIDE
  • WINDOW_REAR_FAR_SIDE
  • WINDOW_REAR_QUARTER_NEAR_SIDE
  • WINDOW_REAR_QUARTER_FAR_SIDE
  • TAIL_LIGHT_NEAR_SIDE
  • TAIL_LIGHT_FAR_SIDE
  • HEAD_LIGHT_NEAR_SIDE
  • HEAD_LIGHT_FAR_SIDE

Interior regions

(Click an item below to copy it to your clipboard)

  • DASHBOARD
  • DOOR_TRIM_FRONT_NEAR_SIDE
  • DOOR_TRIM_REAR_NEAR_SIDE
  • QUARTER_PANEL_TRIM_NEAR_SIDE
  • CARPETS_FRONT
  • CARPETS_REAR
  • REAR_PANEL_TRIM
  • ROOF_LINING
  • PARCEL_SHELF
  • TAILGATE_PAD
  • SEATS_FRONT_FAR_SIDE
  • SEATS_FRONT_NEAR_SIDE
  • SEATS_REAR
  • DOOR_TRIM_FRONT_FAR_SIDE
  • DOOR_TRIM_REAR_FAR_SIDE
  • QUARTER_PANEL_TRIM_OFF_SIDE

Listing Eligibility

This feature is a work in progress so subject to change

It can be useful at points to check if your stock can be listed. For example, your vehicle may not match the stock profile of the network you wish to advertise in, there may not be enough free auction slots or will not pass validation.

You should POST the stock object to /v1/stock-precheck Sending a stock object that is as close to what is being listed will give better guarantees

Successful calls will receive a 200 response, validation failures will respond with a 422 and details of why the validation failed.

Due to the dynamic nature of our site there may be some rare circumstances where we respond with a 200 when called but then the attempt to list the vehicle fails validation. It is recommended that the time between checking eligibility and attempting to list is kept as small as possible to minimise the chance of this occurring.

Name Description
UNSUPPORTED_STOCK This item of stock is currently not supported
THROTTLED Our systems have reached their capacity limit. Please try again later

Listings

A listing is created once an advert has been transitioned to an ACTIVE state.

Each time this happens, a new listing is created. Every listing has a unique ID.

If a vehicle is listed three times, there will be three listings created, each with its own ID. These will relate back to a single stock ID.

When a listing is created via a call to our stock-api, the new listingId value will be returned as part of the stock response. The listingId will also be included in any of our outbound webhook events, for example listing.started.

When you have a listingId it can be used to retrieve additional realtime listing information via our Listings API.

See our reference documentation for more information

Webhooks

Our webhook implementation is currently under active development. All features are subject to change.

To get started, please provide us with a url you want the events to POST to.

We currently only support application/json as the Content-Type.

All requests will be sent over with a User-Agent value of dealer-auction-webhook/1.0.

See our reference documentation for more information

Verifying message signatures

import com.google.common.hash.Hashing
import java.nio.charset.Charset

fun checkSignatureHeader(messageBody: String, secretKeys: List<String>, signatureHeader: String): Boolean {

/* Most of the time, we are dealing with a single key.
However, treating this as a "list of one" rather than a singular value keps things flexible.
A list of keys enables us to temporarily introduce secondary keys without breaking things. */


val signatures = signatureHeader.split(",")

return hasValidSignature(messageBody, secretKeys, signatures)
}

private fun hasValidSignature(messageBody: String, secretKeys: List<String>, hashesFromHeader: List<String>): Boolean {
val generatedHashes = secretKeys.map { key -> generateHash(messageBody, key) }
return generatedHashes.intersect(hashesFromHeader).isNotEmpty()
}

private fun generateHash(body: String, key: String): String {
return Hashing.hmacSha256(toByteArray(key))
.hashBytes(toByteArray(body))
.toString()
}

private fun toByteArray(input: String): ByteArray {
return input.toByteArray(Charset.forName("UTF-8"))
}

We include a digital signature with each outbound request. This signature is contained within a DA-Signature header.

The signature is a hmacSha256 hash of the request body using a shared secret key that we have distributed to you.

You can use this key to create your own hash. If your generated hash matches the hash in the request header then the request is genuine.

Multiple keys

To check the message signature is valid you can execute the following (kotlin):

To help ensure system uptime, it is possible that there may be multiple active keys in circulation for your account. Multiple keys will be split using , character.

Eg 7831297d7fdd3078290338503b798c3266661aaa6dcb4c72fb4b5ed25ebaddd5,87dd29d321fd8cc5fec8065bff4663e3e4105982985f1eb473c37d185a361fa3

This will rarely happen, however we recommend that you treat the signature header as a collection of values rather than a single value.

When extracting signatures from the header, split the header value using , and treat the result as a list. Check each signature in turn. If you get a single match then the request is genuine.

The reasoning for multiple signatures is to enable keys to be rotated and phased out if needed whilst not causing downtime.

Queuing and retries

If a webhook request fails to deliver we will attempt to try 2 additional times at 30 minute intervals.

If a subsequent retry is successful then we will stop retrying.

Any non 2xx response or connection issue will count as a failure.

Events

See our reference documentation for a breakdown of the events that we offer.

Account Linking

We offer the ability for a user to link their DA customer account to a third-party customer account.

This achieved via an OAuth flow.

https://www.oauth.com/oauth2-servers/server-side-apps/example-flow/
https://www.youtube.com/watch?v=t18YB3xDfXI
https://datatracker.ietf.org/doc/html/rfc6749

A diagram of our flow is available here. The process is outlined below.

1. Redirect to Dealer Auction account linking page

Example OAuth redirect to DA

https://www.dealerauction.co.uk/oauth/#/link-account?client_id=Y1D5U0N4Q9B9X&state=pG1wK5kG9dN8eW8dP2mF&=redirect_uri=https%3A%2F%2Fyour-domain.com%2Fcallback-page

The first step is to redirect the user to a page that we host. From here, the user will enter credentials to authorize the linking of accounts. When redirecting to us, you must supply the following parameters

URL parameters:

name description
client_id A unique identifier that we have generated for you required field
redirect_uri A page that you host that we will redirect back to upon successful authorization.

We recommend that this parameter value is URL Encoded to preserve special characters such as ? and &
required field
state A value that you generate. It can be any value but should be unique to a request. A uuid is a good candidate for this.

We will return this value back to you later in the process. It helps guard against CSRF attacks.

https://auth0.com/docs/configure/attack-protection/state-parameters
recommended

The domain of the URI specified by redirect_uri will need to be added to our internal whitelist. This whitelist is administered for you. The scheme of the url must be https, not http.

If either of these required parameters are missing or have incorrect values then the journey will stop. The user will be presented with an error message stating that the account cannot be linked.

2. User will log in to our platform

If the user is already logged in, then this step will be skipped

3. We generate an Authorization Grant

An Authorization Grant will be generated by us on behalf of the user. A short-lived, single-use temporary token is created and acts as a key to identify this grant.

Example OAuth callback

https://your-domain.com/callback-page?code=7394a4ca-54b0-420a-9773-5a42cb971297&state=pG1wK5kG9dN8eW8dP2mF

4. We redirect back to your hosted page and include the temporary token

We use the redirect_uri that was supplied to us. If a state value is included, then this will also be part of the redirect.

OAuth POST body

{
"code": "7394a4ca-54b0-420a-9773-5a42cb971297"
}

OAuth response

{
"access_token": "ad215d9a-9372-4786-a066-1e2b4f09e495"
}

You need to extract the temporary token from the query parameter and use it in the next step.

5. You pass temporary token back to us to generate an access token

An http POST is made to a secured endpoint
https://api.dealerauction.co.uk/{thirdparty-name}/oauth/token

The POST body contains a single field, code. This is the temporary token.

We will locate the authorization grant using the temporary token and use this to generate a permanent access token. This access token is an external key to one of our customers.

6. Fetch customer details via our /customer endpoint.

Example customer request

https://api.dealerauction.co.uk/{thirdparty-name}/customer/ad215d9a-9372-4786-a066-1e2b4f09e495

Example customer response

{
"customerId": "12345",
"tradingName": "the customer trading name",
"canSell": true,
"sellerNetworks": [
"network1",
"network2"
]
}

Once you have an access token, you can use it to view the state of our customer.

To do this, a http GET is made to another secured endpoint
https://api.dealerauction.co.uk/{thirdparty-name}/customer/{access-token}

Response fields:

name description
customerId Our customer ID
tradingName The customers trading name
canSell Whether the customer is currently allowed to sell on the platform
sellerNetworks The networks that the customer is permitted to sell into

Calls to api.dealerauction.co.uk are secured with HTTP basic auth. A username and password will be generated and distributed to you.