# Photos

Photos never travel through MCP tools. They go to two plain HTTP endpoints with the same API key: [upload_media](https://developers.sceniq.earth/reference/upload_media.md) for one photo and [upload_media_batch](https://developers.sceniq.earth/reference/upload_media_batch.md) for up to ten.

## Whose photos

Photos are the creator's own files. Never download images from the web, stock sites or social media, and never generate them. Ask who took each photo: a photo that is not the creator's own carries the photographer's name in `credit`, and credits render everywhere the photo does.

The one exception is a guide the creator asks you to build from licensed photos: then only licences that allow commercial use (the Unsplash License, CC0, CC BY with its attribution), and every photo carries `credit`, `licence`, `sourcePageUrl` and `creditUrl`.

## Upload one photo

Resize to 2,048 px on the long side and compress first (around 80 percent quality, well under 1 MB). Then send the bytes with the owner on the query string:

```bash
curl -X POST "https://sceniq.earth/api/v1/media/upload?ownerType=spot&ownerId=SPOT_ID&credit=Mara%20Lindgren&alt=Rainbow%20rings%20of%20Grand%20Prismatic%20Spring" \
  -H "Authorization: Bearer $SCENIQ_API_KEY" \
  -H "Content-Type: image/jpeg" \
  --data-binary @grand-prismatic.jpg
```

`ownerType` is `spot`, `product` (store thumbnail and sales page material), `collection` (a chapter) or `listing` (sales page slides). Multipart with a `file` field and the same fields works too.

## What the server does

It checks the real file type (JPEG, PNG or WebP; at most 6 MB and 6,000 px per side), applies the EXIF rotation, scales the long side to 2,048 px, stores WebP without EXIF, GPS, XMP or IPTC metadata, and keeps the capture date as `capturedOn`. Photos get a 640 px thumbnail the apps use for maps, lists and offline downloads. The response is the new photo with its `mediaId`.

## Several photos at once

```bash
curl -X POST "https://sceniq.earth/api/v1/media/upload-batch" \
  -H "Authorization: Bearer $SCENIQ_API_KEY" \
  -F 'manifest=[{"file":"a","ownerType":"spot","ownerId":"SPOT_ID","credit":"Mara Lindgren","alt":"The spring from the overlook"}]' \
  -F "a=@overlook.jpg"
```

Each file succeeds or fails on its own; the response lists every result. Each file counts against the upload limit.

## Chapter covers and intro photos

`target=blob` stores the file without a media row and returns a `storageId`: pass it as `coverStorageId` to [update_chapter](https://developers.sceniq.earth/reference/update_chapter.md) or as `photoStorageId` in [set_chapter_intro](https://developers.sceniq.earth/reference/set_chapter_intro.md) sections.

## After the upload

- Upload each photo once. Keep the `mediaId`; change captions, credits and the rest with [update_media](https://developers.sceniq.earth/reference/update_media.md). To replace a photo, upload the new one and [delete_media](https://developers.sceniq.earth/reference/delete_media.md) the old one.
- Upload the full framing and set a focal point (`focalX`, `focalY` from 0 to 1) instead of cropping: the apps crop per surface and keep that point in frame.
- Write `alt` for what the photo shows; the caption is what buyers read under it.
- Say what it shows (`shows`) and, when known, where it was taken (`takenAt` with its precision) and how that was confirmed (`locationVerifiedBy`). Readiness flags a precise location more than 2 km from the pin, and photos taken before a change at the spot.
- [reorder_media](https://developers.sceniq.earth/reference/reorder_media.md) moves a photo in its gallery; [list_media](https://developers.sceniq.earth/reference/list_media.md) shows every photo with its fields.

A guide publishes only when every live spot with photos turned on has at least one photo.
