Inventory API
The Inventory API writes stock into Vyro: from a dealer management system, a feed, or your own platform. To read stock, use the GraphQL API.
| Environment | Base URL |
|---|---|
| Staging | https://inventory-api.vyrolabs-staging.net |
| Production Asia-Pacific | https://inventory-api.vyro.com.au |
| Production Europe | https://inventory-api.vyro-eu.com |
The OpenAPI specification is at /spec on each host, with no token needed. Point a code generator at it for a typed client.
Authentication
Section titled “Authentication”Use the same bearer token as the GraphQL API (Authentication). Each batch has a source_name that says who owns the vehicles:
| Client | source_name |
Can write to |
|---|---|---|
| User client | user:<the user's id>, or leave it out |
Showrooms that user belongs to |
| App client | app:<your app code> |
Showrooms that installed your app |
Vehicles are keyed by source_name plus your source_id. Sending the same source_id again updates the vehicle.
Send a batch
Section titled “Send a batch”-
POST up to 100 vehicles (or 2 MB) to
/batch.Terminal window curl -s https://inventory-api.vyrolabs-staging.net/batch \-H "Authorization: Bearer $ACCESS_TOKEN" \-H 'Content-Type: application/json' \-d @batch.json{"source_name": "user:3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f","items": [{"showroom_ids": ["9b1d4e7a-2c3f-4a5b-8d6e-7f8091a2b3c4"],"vehicle": {"source_id": "STK-1042","stock_id": "1042","condition": "used","production_year": "2022","make": "Hyundai","model": "Kona","badge": "Active","vin": "KMHK281EMNU000000","odometer": 38500,"colour": "Ultimate Red","body_type": "SUV","fuel_type": "petrol","transmission": "Automatic","is_published": true,"is_listed": true,"is_sold": false,"estimated_delivery_delay": 0,"pricing": {"type": "basic","price": 2299000,"currency": "AUD"}},"location": { "source_id": "sydney", "name": "Example Motors Sydney" },"assets": [{ "type": "image", "placement": "featured", "order": 0, "src": "https://example.com/1042/front.jpg" },{ "type": "image", "placement": "gallery", "order": 0, "src": "https://example.com/1042/side.jpg" },{ "type": "image", "placement": "gallery", "order": 1, "src": "https://example.com/1042/interior.jpg" }]}]}You get a job id back straight away, with status
201:{ "job_id": "6859392d-d604-4ca6-8842-28494e2bbc1b" } -
Poll the job at
GET /jobs/{job_id}untilstatusiscompleted. Batches usually finish within a minute.{"id": "6859392d-d604-4ca6-8842-28494e2bbc1b","status": "completed","errors": [],"image_moderation": [{"index": 4,"accepted": [{ "src": "https://ik.imagekit.io/vyro/…" }],"rejected": [{ "src": "…", "original_src": "https://example.com/1042/banner.jpg" }]}]} -
Read the result with GraphQL, by
source_id, to get each vehicle’sidandcode.query Imported($sourceIds: [String!]!) {stocked_vehicles(where: { source_id: { _in: $sourceIds } }) {idcodesource_idis_published}}
Required vehicle fields
Section titled “Required vehicle fields”source_id, production_year (a string such as "2022"), make, model, condition (new, used or demo), is_published, is_listed, is_sold and estimated_delivery_delay (days until it can be delivered; 0 if it’s on the lot). Everything else is optional, but the more you send, the better the listing. The specification lists every field.
odometeris in kilometres.fuel_typeis one ofpetrol,diesel,electric,hybrid,plug-in-hybrid,hydrogen,lpg.- Dates are
YYYY-MM-DD.
Prices
Section titled “Prices”Prices are in cents. Choose one of two shapes.
pricing (basic): one price, used for every state the showroom sells in.
"pricing": { "type": "basic", "price": 2299000, "currency": "AUD", "excls_on_roads": false }advanced_pricing: a full price per state. Use this when drive-away prices differ by state, which in Australia they usually do.
"advanced_pricing": { "type": "advanced", "items": [ { "pricing_code": "AU_NSW", "version": "v2", "driveAwayPrice": 3069000, "lineItems": { "dutiable": [{ "code": "vehicle-price", "value": 2850000 }], "onRoad": [{ "code": "stamp-duty", "value": 114000 }, { "code": "registration", "value": 105000 }], "additional": [] } }, { "pricing_code": "AU_VIC", "version": "v2", "driveAwayPrice": 3099000, "lineItems": { "dutiable": [{ "code": "vehicle-price", "value": 2850000 }], "onRoad": [{ "code": "on-road-costs", "value": 249000 }], "additional": [] } } ]}A vehicle is only offered in the states you send. To calculate state drive-away prices, use the Pricing API.
Images
Section titled “Images”srcmust be a public HTTPS URL. Vyro downloads each image, checks it, and re-hosts it on its image CDN, so thesrcyou read back is different from the one you sent.placementisfeaturedfor the hero (one per vehicle) andgalleryfor the rest.ordercounts from 0 within each placement.- Images are checked against Vyro’s acceptable use policy. Rejected ones (for example, text-only promotional graphics) are listed in the job’s
image_moderation.rejected, with youroriginal_src.
Mark a vehicle sold or remove it
Section titled “Mark a vehicle sold or remove it”Send the vehicle again in a batch with the same source_id and the new flags:
- Sold:
is_sold: true. Its page stays up and says it’s sold. - Hidden from lists, still reachable by link:
is_listed: false. - Off the site:
is_published: false.
Send the whole vehicle each time, including its images, because a batch item replaces the vehicle.
Limits
Section titled “Limits”- 100 vehicles or 2 MB per batch.
- 10,000 requests per minute. Above that you get
429 Too Many Requests: back off and retry.