SMC API v1.0
SMC API v1.0 is a server-to-server quote API for international car dealers, listing sites, marketplaces, and relocation companies. It returns transport quotes for UK, EU, and selected international vehicle movements, with optional destination import-tax and registration estimates for UK and EU arrivals. View the API brochure.
UK road transport
Instant UK collection and delivery estimates for dealer stock, private sales and relocations.
UK and EU movements
Quote UK-to-EU, EU-to-UK, and EU-to-EU vehicle transport with destination tax and registration context.
International sea freight
Support overseas enquiry flows with international shipping, customs and arrival-cost estimates.
Taxes and registration
Return display-ready estimates for customs taxes, testing and registration into the UK and all EU countries.
Endpoint
POST /api/v1/quotesAuthentication
x-api-keyFormat
application/jsonOverview
The API is intended for trusted server-to-server integrations. Do not place API keys in browser JavaScript, mobile apps, or public repositories.
Supported route types
eu-to-eu quotes any route between two EU countries, including moves within a single EU country. Unlike uk-to-eu and eu-to-uk, transport.items has no customs clearance line (there is no UK border crossing), and destinationCosts.importTaxesdefaults to EU free circulation (see destinationCostDetails.inFreeCirculation in Request Body), so duty and VAT are typically €0. Registration estimates remain fully supported. EU-to-EU transport pricing also has a €300 customer-facing minimum charge, so very short routes will not quote below that floor.Authentication
Send the API key in the x-api-key request header. SMC API v1.0 only accepts active, non-expired API keys from the API users database.
unauthorized to avoid leaking account state. If the key cannot be checked because of a temporary service problem, the API returns HTTP 503 with service_unavailable instead; this does not mean the key is invalid, so retry after the Retry-After delay rather than replacing the key.Request Body
Submit nested JSON. Vehicle details may be provided manually or supplied through a 17-character VIN. Live VIN lookups use the SMC VIN Lookup Server, with a permanent global cache so the same VIN is not looked up twice. Monthly VIN allowances are counted as unique normalized VINs per API user per UK calendar month.
| Field | Type | Required | Description |
|---|---|---|---|
partnerReference | string | No | Your own quote or listing reference. Returned unchanged in the response. |
collection.country | string | Yes | Collection country name or 2-letter country code. |
collection.address | string | Yes | Collection address or city. It must be specific enough to geocode. |
collection.coordinates | [longitude, latitude] | No | Optional exact collection coordinates. When supplied, these are used for transport pricing to match website quotes for the same route. |
collection.countryCode | string | No | Optional 2-letter country code. If supplied, it is preferred for route normalization. |
delivery.country | string | Yes | Delivery country name or 2-letter country code. |
delivery.address | string | Yes | Delivery address or city. It must be specific enough to geocode. |
delivery.coordinates | [longitude, latitude] | No | Optional exact delivery coordinates. When supplied, these are used for transport pricing to match website quotes for the same route. |
delivery.countryCode | string | No | Optional 2-letter country code. If supplied, it is preferred for route normalization. |
vehicle.vin | string | No | Optional 17-character VIN. Real VINs are decoded through the SMC VIN Lookup Server with a permanent global cache; configured demo VINs are decoded locally. |
vehicle.year | number | If no VIN | Vehicle year. Required when not supplied by a valid VIN lookup. |
vehicle.make | string | If no VIN | Vehicle make. Required when not supplied by a valid VIN lookup. |
vehicle.model | string | If no VIN | Vehicle model. Required when not supplied by a valid VIN lookup. |
vehicle.value | number | Yes | Vehicle value used for freight, import tax, and destination-cost estimates. |
vehicle.currency | GBP | EUR | USD | AED | AUD | CAD | CHF | HKD | JPY | NZD | ZAR | No | Currency for vehicle.value. Defaults to GBP when omitted. |
vehicle.type | string | No | Optional vehicle category. vehicleType is also accepted. Defaults to car. |
vehicle.fuelType | string | No | Optional fuel type used by some destination registration calculations. |
vehicle.engineSize | number | Recommended for no-VIN classics | Engine capacity in cc. This is the most useful optional field for pre-1981/no-VIN EU registration estimates because it disambiguates power, tax class, and model variants. A value below 10 is treated as litres (e.g. 3 becomes 3000cc) and converted automatically. |
vehicle.firstRegistrationDate | YYYY-MM-DD | No | Optional first registration date. If omitted for a classic no-VIN vehicle, v1 may use January 1 of vehicle.year as an estimate assumption. |
transport.shippingMethod | open | enclosed | No | Preferred transport method. Defaults to open. transport.method is accepted as a backwards-compatible alias. |
transport.nonRunner | boolean | No | Set true when the vehicle cannot be driven. Defaults to false. |
transport.skipUKTransport | boolean | No | Set true to omit the UK inland transport leg where supported. |
options.targetCurrency | currency code | No | Display currency for transport quote totals. Defaults to GBP. |
options.includeDestinationImportTaxes | boolean | No | Set true to estimate destination import duty/VAT where available. |
options.includeDestinationRegistrationEstimate | boolean | No | Set true to estimate destination registration or arrival costs where available. |
destinationCostDetails | object | No | Optional country-specific details for import and registration estimates. |
Demo VINs
Demo VINs are still available for integration testing and do not call the SMC VIN Lookup Server.
| VIN | Description |
|---|---|
SMCDEMVW2020GLF1X | 2020 Volkswagen Golf demo profile |
SMCDEMBMW2023M4XX | 2023 BMW M4 Competition demo profile |
VIN request
Pre-1981 / no-VIN classic request
EU-to-EU request
eu-to-eu covers any route where both collection and delivery are EU countries, including moves within a single EU country as well as cross-border moves such as the Netherlands-to-Germany example below.
Pre-1981 and no 17-character VIN vehicles
Minimum partner input is vehicle.year, vehicle.make, vehicle.model, vehicle.value, vehicle.currency, collection, delivery, and the destination-cost options. A VIN is not required for cars that pre-date the modern 17-character VIN format.
Send vehicle.engineSize whenever available. It is the best extra field for classic EU registration estimates because it helps distinguish variants, power figures, tax class, and fuel/engine family. Fuel type, first registration date, power, body style, and destination-specific local documents should also be sent when known.
v1 may default first registration to January 1 of the vehicle year, use the quoted vehicle value as a local-market-value proxy, default France to department 75, default Belgium to Flanders, and use cached source-backed specification lookup for unresolved technical fields. CO2 is not invented for pre-1981 cars; if it cannot be source-backed, the response keeps the field missing or returns a lower-confidence estimate with warnings.
destinationCosts.missingFields and destinationCosts.messages.warnings before showing the result to a customer.metadata.exchangeRateUsed.Destination cost detail inputs
These fields are optional and only needed when requesting destination import-tax or registration estimates. The API accepts the nested object names below; aliases are shown where supported.
| Field | Type | Description |
|---|---|---|
destinationCostDetails.registrationCountry | string | Current registration or origin country. Defaults to the collection country when omitted. |
destinationCostDetails.vehicleDetails | object | Optional country-specific vehicle facts for EU registration estimates, such as CO2, weight, first registration date, power, seats, or department code. euVehicleDetails is accepted as an alias. |
destinationCostDetails.exportDetails | object | Optional EU import/export facts such as import date, origin country, free-circulation status, or transfer-of-residence context. euExportDetails is accepted as an alias. |
destinationCostDetails.hmrcDetails | object | Optional UK import-tax details. ukImportDetails is accepted as an alias. |
destinationCostDetails.dvlaDetails | object | Optional UK registration details. ukRegistrationDetails is accepted as an alias. |
destinationCostDetails.arrivalDate | ISO date | Optional arrival/import date for EU destination-cost calculations. importDate and expectedArrivalDate are also accepted. |
destinationCostDetails.inFreeCirculation | boolean | Optional top-level alias for destinationCostDetails.exportDetails.inFreeCirculation. EU-to-EU requests default to true when omitted. |
destinationCostDetails.vehicleDetails
EU destination registration calculators use these vehicle facts when they are not already known from a VIN lookup. Send only the values that apply to the destination country and vehicle.
| Field | Type | Description |
|---|---|---|
fuelType | petrol | diesel | hybrid | electric | ... | Fuel type. Usually supplied by the demo VIN, but may be supplied manually. |
engineSize | number | Engine capacity in cc. Strongly recommended for pre-1981/no-VIN vehicles. |
firstRegistrationDate | YYYY-MM-DD | First registration date. Used for vehicle age, classic, and registration-tax rules. |
co2Emissions | number | CO2 emissions in g/km. Usually unavailable or non-official for pre-1981 vehicles; do not guess this value. |
co2Standard | wltp | nedc | CO2 measurement standard when CO2 is supplied. For Portugal and Denmark, v1 derives it from the first-registration date or year when omitted (WLTP from September 2018), with a warning. |
euroStandard | string | Emissions standard, for example euro6d or euro0. |
powerKw / netPowerKw | number | Power in kW. Some destination registration formulas use one or both values. |
vehicleWeightKg / maximumAuthorizedMassKg | number | Weight values used by some EU registration formulas. Denmark derives CO2 from vehicleWeightKg when no CO2 figure is supplied, so send the unladen weight where known. For a car whose running-order weight (with fuel and driver) is 2,585 kg or more, send that weight instead: Denmark uses a different formula for those cars. If Denmark has neither a CO2 figure nor a weight from the request or the VIN, v1 uses a published CO2 figure or, failing that, a published weight from a source-backed lookup, or else a typical weight for the engine size, age and body, and says so in the warnings. |
localMarketValue | number | Estimated local market value where a destination tax calculation requires it. |
originalNewPriceDkk | number | Denmark only, optional: the original price of the car as new in DKK, including VAT and excluding registration tax. original_new_price_dkk is also accepted. It caps the taxable value of a used import aged 5 years or more (assuming the car has not been registered in Denmark before), reduces the tax for the value loss when the taxable value is below it, and caps the tax of a car more than 35 years old at the tax on 75% of this price. When it is omitted for a car aged 30 or more, v1 looks up a published price as new and converts it to DKK (fixed euro conversion rates for pre-euro currencies, today's exchange rate otherwise; neither is the rate when the car was new, so supply this field for a firmer figure). If none is found, a car more than 35 years old is quoted at the ordinary value tax, assuming it is worth at least 75% of its price as new (the note gives the absolute ceiling, 150% of the value basis, for a car worth less), and a younger car without the cap. The warnings say which applied. |
departmentCode | string | French department code, for example 75. |
belgiumRegion | flanders | wallonia | brussels | Belgian registration region when Belgium is the destination. |
vehicleTypeApproval | eu | national_or_isolated | French type-approval status where relevant. |
destinationCostDetails.exportDetails
| Field | Type | Description |
|---|---|---|
originCountry | country code | Origin/current registration country, for example GB, US, DE. |
importDate | YYYY-MM-DD | Expected EU import/arrival date. arrivalDate is also accepted at destinationCostDetails level. |
inFreeCirculation | boolean | For EU-origin arrivals, whether the vehicle is already in EU free circulation. May also be supplied directly as destinationCostDetails.inFreeCirculation. |
exportPurpose | permanent | temporary | Import/export purpose where the destination calculator needs it. |
transferOfResidence | boolean | Set true where transfer-of-residence relief may apply. |
destinationCostDetails.ukImportDetails
Used for UK arrivals when options.includeDestinationImportTaxes is true. hmrcDetails is accepted as an alias.
| Field | Type | Description |
|---|---|---|
importDuration | permanent | temporary | Whether the UK import is permanent or temporary. |
isCommercialImport | boolean | Set true for commercial imports. |
importReason | string | Optional reason such as returning, gift, inheritance, or moving. |
transferOfResidence | boolean | Set true if transfer-of-residence relief may apply. |
ownershipDuration | string | Ownership duration for relief checks, where relevant. |
isReturningVehicle | boolean | For importReason "returning": true if the vehicle was registered in the UK before it left. Skips IVA and the DVLA first registration fee. |
previouslyRegisteredInUk | boolean | For importReason "returning": true if the importer owned the vehicle when it left the UK and it has not changed hands abroad. Both flags true gives Returned Goods Relief (0% duty, 0% VAT); false here gives duty relief only (0% duty, 20% VAT). |
hasEuStatementOnOrigin / hasEuExporterNumber | boolean | Optional EU origin-proof flags for preferential-duty checks. |
hasJapanStatementOnOrigin / hasJapanCorporateNumber | boolean | Optional Japan origin-proof flags for preferential-duty checks. |
destinationCostDetails.ukRegistrationDetails
Used for UK arrivals when options.includeDestinationRegistrationEstimate is true. dvlaDetails is accepted as an alias.
| Field | Type | Description |
|---|---|---|
registrationCountry | string | Country where the vehicle is currently registered. |
hasRearFog | yes | no | unsure | Whether the vehicle already has a compliant rear fog light. |
fogLightPosition | left | right | centre | Fog-light position when hasRearFog is yes. |
hasMph | yes | no | unsure | Whether the speedometer displays mph. |
dashboardType | analogue | digital | Used when mph conversion may be required. |
hasCoC | yes | no | unsure | Certificate of Conformity status for relevant EU vehicles. |
isHalogen | yes | no | unsure | Used for some headlight-conversion estimates. |
Nested object shape
Success Response
A successful request returns HTTP 200 with success: true. A quote is usable when quotable is also true.
| Field | Type | Description |
|---|---|---|
success | boolean | True when the API request was processed successfully. |
quotable | boolean | True when a transport quote could be calculated. |
partnerReference | string | null | The partner reference supplied in the request. |
route | object | Route type, support flag, and collection/delivery regions. |
vehicle | object | Normalized vehicle year, make, model, value, and currency used for the quote. |
vin | object | Safe VIN status only: supplied, decoded, demo, partial, source, and cache flags. Raw decoded VIN data is not returned. |
transport | object | Transport line items, subtotal, pricingView, and amountMode. |
destinationCosts | object | Optional import tax and destination registration estimates. Deep calculation traces are intentionally not returned. |
destinationCosts.messages.warnings | string[] | One sentence per default, source-backed value or assumption behind an EU registration estimate (for example a classic no-VIN default or a Denmark weight or price as new), with its source. The structured enrichment record behind these notes is kept internally and is not part of this response. |
totals | object | Transport total, destination estimate total, currencies, and combined total when currencies match. |
metadata | object | Public metadata only: source, item count, destination-cost status, exchange-rate summary, cache status, and canContinue when available. |
metadata.exchangeRateUsed | object | The rate direction used for value-sensitive calculations. vehicleCurrencyPerGbp means one GBP equals this many units of vehicle.currency; eurPerGbp is included when EU estimates use it. |
apiLogId | uuid | Returned for quotable responses when the continue quote link is available. |
expiresAt | ISO date | Expiration for the continue quote link. Links currently expire after 30 days. |
continueQuoteUrl | string | A URL that lets the customer continue the quote on ShipMyCar with the quote data pre-filled. |
Cache status
Returned at metadata.cache.quote when quote-cache metadata is available.
| Status | Meaning |
|---|---|
refreshed | The API ran a fresh full quote calculation. |
full_cached | The full quote response was served from cache for an identical request. |
routing_cached_taxes_fresh | Routing was reused, while value/currency-sensitive transport, tax, registration, and totals were recalculated. |
Example response
Line Items
Transport and destination costs use different row contracts. Transport rows are quote charges payable to ShipMyCar. Destination rows are estimates for import tax, registration, or environmental charges in the arrival country.
Destination rows do not include summary rows such as total payable. Use section subtotals and destinationCosts.total for totals.
For pricingView: customer_sell_price, transport item amount is already gross including VAT. Do not add vat again when calculating customer totals.
transport.items[]
| Field | Type | Description |
|---|---|---|
description | string | Plain-text transport or service description. HTML is stripped from the public response. |
amount | number | Line item amount in the transport quote currency. For customer_sell_price/gross_including_vat, this is the customer payable amount. |
vat | number | VAT component included in amount where VAT applies. |
optional | boolean | Whether the item is optional. |
uk-to-eu and eu-to-uk quotes include a separate customs clearance charge line. eu-to-eu quotes do not, since there is no UK border crossing: transport.itemsis normally the single insured road-transport line.destinationCosts.*.items[]
| Field | Type | Description |
|---|---|---|
key | string | Stable display key for the row, such as import-vat or fr-y3. |
type | import_tax | registration | environmental | Destination-cost section this row belongs to. |
label | string | Display label for the cost row. |
amount | number | Numeric amount. Discounts are negative values. |
formattedValue | string | Human-readable value, formatted by the API for display. |
unavailable | boolean | True when a row is shown but not calculable. |
available: true with status: 'full' and still return an empty items array when every row in it rounds to zero: for example importTaxes.items on a free-circulation eu-to-eu quote. Use the section subtotal, not the presence of rows, to detect a zero result.Destination Costs
Destination costs are optional. Set options.includeDestinationImportTaxes and/or options.includeDestinationRegistrationEstimate to request them. If a section cannot be calculated, the response returns status and messages explaining what is missing.
international-to-eu routes. Requesting options.includeDestinationRegistrationEstimate on those routes returns the registration section with status unsupported. Import taxes and freight are unaffected.vehicle.value or vehicle.currency changes, taxes and value-sensitive transport costs are recalculated while route selection may be reused from cache.Import taxes
Returned under destinationCosts.importTaxes. Includes duty, VAT, subtotal, and display rows.
Registration estimate
Returned under destinationCosts.registration. Includes subtotal, tax name, optional notice, and display rows.
Messages
User-facing destination-cost messages are grouped by purpose:
EU-to-EU example response
This continues the Netherlands-to-Germany request from Request Body. originCountrydefaults to the collection country and inFreeCirculation defaults to true for eu-to-eu, so importTaxes is available: true with duty and VAT at €0.00 and no rows in items. Registration is unaffected by free circulation and still calculates normally: Germany has no CO2/value-based registration tax, so the estimate is an administrative fee only.
Classic no-VIN enrichment
For pre-1981 or 30+ year EU registration estimates without a VIN, v1 may default or source-backed technical fields before calculating. Each default or sourced field is one sentence in destinationCosts.messages.warnings; the structured enrichment record is kept internally and is not part of the /api/v1/quotes response.
Denmark always gets a registration estimate. A car with no CO2 figure or weight, of any age and with or without a VIN, gets a source-backed published CO2 figure or, failing that, a published weight, because Denmark derives CO2 from the weight; without either it gets a typical weight for its engine size, age and body. A car aged 30 or more without originalNewPriceDkk gets a source-backed published price as new; if none is found, a car more than 35 years old is quoted at the ordinary value tax, assuming it is worth at least 75% of its price as new, and the note gives the absolute ceiling (150% of the value basis) for a car worth less. Each assumption, with its source and which way it may be wrong, is one sentence in destinationCosts.messages.warnings.
Defaults and source-backed fields are used only to keep registration estimates moving when the request has enough identifying facts. Raw AI prompts, raw model responses, and deep calculation traces are not exposed.
Continue Quote URL
Quotable responses include a continueQuoteUrl. Send the customer to this URL to load the vehicle, route, transport, and cost data into the ShipMyCar quote flow.
Continue links currently expire after 30 days. Treat the URL as a bearer token: anyone with the URL can open the saved quote data until it expires.
Error Responses
Error responses are sanitised. Known validation errors include field-level details; internal calculation and infrastructure failures do not expose raw exception data.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_json | Request body was not valid JSON. |
| 400 | invalid_request | Request JSON was valid, but failed schema validation. |
| 400 | invalid_vin | A supplied VIN was not a valid 17-character VIN. |
| 400 | missing_vehicle_data | Vehicle year, make, model, or value was missing. |
| 401 | missing_api_key | The x-api-key header was not supplied. |
| 401 | unauthorized | The API key is invalid, inactive, or expired. |
| 413 | payload_too_large | The request body was larger than 64 KB (65,536 bytes). Quote requests are normally a few KB. |
| 422 | unsupported_route | The route is unknown or not supported by SMC API v1.0. |
| 429 | rate_limit_exceeded | A request rate limit was exceeded. Sent with Retry-After and RateLimit-* headers indicating when to retry. |
| 429 | vin_lookup_allowance_exceeded | The API user has exceeded its monthly unique VIN lookup allowance. |
| 503 | vin_lookup_cache_unavailable | The permanent VIN lookup cache is unavailable, so the API did not call the SMC VIN Lookup Server. |
| 503 | vin_lookup_unavailable | The live VIN lookup service is not configured or unavailable. |
| 503 | service_unavailable | The API key could not be checked because a backing service was temporarily unavailable. The key was not rejected. Sent with a Retry-After header; retry after that many seconds. |
| 422 | quote_not_calculable | The route was supported, but a quote could not be calculated from the supplied data. |
| 400 | partner_quote_error | Known quote calculation failure that does not expose internal details. |
| 500 | partner_quote_failed | Unexpected server-side failure. The response is sanitised. |
rate_limit_exceeded and includes Retry-After and RateLimit-*response headers. Back off until the time indicated by Retry-After before retrying.Validation error example
Migration Notes
The old public documentation described /api/getallcosts. SMC API v1.0 uses /api/v1/quotes and a nested request model.
The response intentionally omits internal fields that were present in older responses, including quoteCostId, route database IDs, calculation traces, selected haulier IDs, legacy metadata, and raw decoded VIN data.
For display, use transport.items, destinationCosts.importTaxes.items,destinationCosts.registration.items, section subtotals, and destinationCosts.total.
Currency and pricing policy are reported in transport and totals. They are not repeated as top-level response fields. Exchange-rate information is reported once in metadata.exchangeRateUsed.