Ipswich stock photo library
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.
Drop hundreds of originals at once. Camera, lens, exposure, dimensions and capture date are read from each file automatically.
Render the gallery with your own markup and styling. Keyset pagination powers infinite scroll; filter by tag or search.
Every photo exposes a direct download link for the untouched original. You decide who can reach it on your site.
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.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/photos | Paginated list. Query: limit, cursor, tag, q. |
| GET | /api/photos/:id | Single photo with full metadata. |
| GET | /api/photos/:id/download | Streams the full-resolution original as a download. |
| GET | /api/tags | All tags for building filters. |
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…"
}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
}