HGV Traders Docs

Image uploads

Upload stock photos and attach image keys to listings.

Overview

Most integrations upload photos in one step, then attach the returned image key to a stock listing.

StepActionAuth
1POST /api/v1/uploads with the image fileBearer token
2Include the returned key in imageKeys on POST or PATCH /api/v1/stockBearer token

See Stock API for create, update, and publish routes.

Allowed formats

TypeTypical extension
image/jpeg.jpg, .jpeg
image/png.png
image/webp.webp
image/heic.heic

Up to 50 image keys per listing. Direct upload accepts files up to 4MB. Larger files use the presigned upload flow below.

Upload an image

curl -X POST "https://hgvtraders.com/api/v1/uploads" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "file=@front-three-quarter.jpg" \
  -F "organisationId=clorg123abc"

When adding photos to an existing draft, include stockId:

curl -X POST "https://hgvtraders.com/api/v1/uploads" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "file=@side-view.webp" \
  -F "organisationId=clorg123abc" \
  -F "stockId=clstk456def"

Form fields

FieldRequiredDescription
fileYesImage binary
organisationIdWhen multi-orgRequired when the user belongs to more than one organisation — see Accounts
stockIdNoOmit for new listings; set when uploading to an existing draft

Response (201 Created)

{
  "data": {
    "key": "orgs/clorg123abc/temp/1717243200123-a1b2c3d4.jpg"
  }
}

Store the key — not a public URL. HGV Traders serves images from these keys on the website.

Image key patterns:

  • New listing (no stockId): orgs/{organisationId}/temp/{timestamp}-{uuid}.{ext}
  • Existing draft (stockId set): stock-images/{stockId}/{timestamp}-{uuid}.{ext}

If stockId does not belong to your organisation, the API returns 404.

Attach keys to stock

Pass an ordered array of keys when creating or updating a listing:

{
  "title": "2020 DAF XF 530",
  "imageKeys": [
    "orgs/clorg123abc/temp/1717243200123-a1b2c3d4.jpg",
    "orgs/clorg123abc/temp/1717243200999-e5f6g7h8.jpg"
  ]
}

On PATCH, send the complete gallery you want — the array replaces the previous one.

End-to-end example

TOKEN="your_bearer_token"
ORG="clorg123abc"

# 1. Upload photo A
KEY_A=$(curl -s -X POST "https://hgvtraders.com/api/v1/uploads" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@front.jpg" \
  -F "organisationId=$ORG" | jq -r '.data.key')

# 2. Upload photo B
KEY_B=$(curl -s -X POST "https://hgvtraders.com/api/v1/uploads" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@rear.jpg" \
  -F "organisationId=$ORG" | jq -r '.data.key')

# 3. Create draft listing
curl -X POST "https://hgvtraders.com/api/v1/stock" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"organisationId\": \"$ORG\",
    \"assetClass\": \"TRUCK\",
    \"title\": \"2020 DAF XF 530\",
    \"priceType\": \"FIXED\",
    \"pricePence\": 4500000,
    \"locationPostcode\": \"M1 1AA\",
    \"imageKeys\": [\"$KEY_A\", \"$KEY_B\"]
  }"

Then publish with POST /api/v1/stock/{id}/publish — see Stock API.

Large files (advanced)

Phone originals and uncompressed HEIC files often exceed the 4MB direct upload limit. When POST /api/v1/uploads returns 413, use the presigned flow:

  1. POST /api/v1/uploads/presign with filename and contentType (optional stockId)
  2. PUT the file bytes to the returned urlno bearer token on this request; use the same Content-Type as presign
  3. Include the returned key in imageKeys
# Presign
curl -X POST "https://hgvtraders.com/api/v1/uploads/presign" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "organisationId": "clorg123abc",
    "filename": "large-photo.heic",
    "contentType": "image/heic"
  }'
{
  "data": {
    "url": "https://…upload?signature=…",
    "key": "orgs/clorg123abc/temp/1717243200123-a1b2c3d4.heic"
  }
}
# Upload to presigned URL
curl -X PUT "$PRESIGNED_URL" \
  -H "Content-Type: image/heic" \
  --data-binary @large-photo.heic

The presigned url expires after 5 minutes. Request a fresh one if the upload fails or times out.

Errors

StatusCause
400Invalid body, unsupported file type, or missing organisationId for multi-org users
401Missing or invalid bearer token
404stockId not found or not owned by your organisation
413File over 4MB on direct upload — use presign
429Write rate limit exceeded — see Rate limits