Ipswich.co.ukPhoto Library

Ipswich stock photo library

The town's photography, ready to embed anywhere.

Bulk-upload full-resolution photos of Ipswich with automatic EXIF extraction, title and tag them, then serve the whole collection to your website through a simple JSON API. Access control stays on your side.

Bulk upload + EXIF

Drop hundreds of originals at once. Camera, lens, exposure, dimensions and capture date are read from each file automatically.

JSON API embed

Render the gallery with your own markup and styling. Keyset pagination powers infinite scroll; filter by tag or search.

Full-res downloads

Every photo exposes a direct download link for the untouched original. You decide who can reach it on your site.

Embed API

All endpoints are public and CORS-enabled so they can be called directly from your website. Restrict who reaches your gallery page and the download links on ipswich.co.uk.

MethodEndpoint
GET/api/photos
GET/api/photos/:id
GET/api/photos/:id/download
GET/api/tags

Response shape

GET /api/photos
GET /api/photos?limit=24&tag=waterfront&cursor=<next>

{
  "data": [
    {
      "id": "…",
      "title": "Ipswich Waterfront at dusk",
      "url": "https://…/full-res.jpg",
      "thumbUrl": "https://…/thumb.jpg",
      "downloadUrl": "https://…/api/photos/…/download",
      "width": 6000, "height": 4000,
      "tags": ["waterfront", "sunset"],
      "camera": { "make": "SONY", "model": "A7 IV", "iso": 100 },
      "takenAt": "2025-06-01T19:24:00.000Z"
    }
  ],
  "nextCursor": "eyJ…"
}

Infinite scroll in your markup

gallery.js
async function loadGallery(cursor) {
  const url = new URL("https://your-app.vercel.app/api/photos")
  url.searchParams.set("limit", "24")
  if (cursor) url.searchParams.set("cursor", cursor)

  const res = await fetch(url)
  const { data, nextCursor } = await res.json()

  for (const photo of data) {
    const card = document.createElement("a")
    card.href = photo.downloadUrl        // gated on your site
    card.innerHTML = `<img src="${photo.thumbUrl}" alt="${photo.title}">`
    document.querySelector("#gallery").append(card)
  }
  return nextCursor // pass back in to load the next page
}