Overview
This site provides a high level overview of our APIs.
Reference documentation is available here:
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
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
...
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.
- A
temporary token
is single use and so can only be redeemed once. The token is also short-lived, it expires after 60 seconds. If the token has expired, then the account journey must be restarted so that a fresh token can be generated.
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
endpointhttps://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.