POST/api/v4/locations/photos

Upload photos to a location

Attaches media to a location, either by public image URL or by referencing files already in your media library.

Requires an API key. See Authentication for header format and key rotation.

Parameters

Body

A nested field marked required applies only when you send its parent. If the parent is optional and you omit it, its required children do not apply.

NameTypeRequiredDescription
input.locationIdstringrequiredThe location's Base64-encoded Relay ID to attach media to.
input.photosarray of objectsrequiredImages to attach. `photo` is the only required key on each item.
input.photos[].photostringrequiredA publicly accessible JPEG or PNG URL that Listings API fetches and stores. The field is named `photo`, not `url`.
input.photos[].typestringoptionalWhich slot the image fills: `LOGO`, `COVER`, or `ADDITIONAL`. Defaults to an additional photo.
input.photos[].starredbooleanoptionalStar the photo as it is attached, instead of a follow-up call to the star endpoint. Only additional photos can be starred, at most 4 per location.
input.photos[].sourcestringoptionalFree-text label recording where the image came from.

Sample request

Ready-to-paste body. Replace placeholder IDs and values with yours.

Request body
{  "input": {    "locationId": "TG9jYXRpb246MTgwMDI4OQ==",    "photos": [      { "photo": "https://cdn.example.com/jenny-home/logo.png", "type": "LOGO" },      { "photo": "https://cdn.example.com/jenny-home/storefront.jpg", "type": "ADDITIONAL" }    ]  }}

Responses

200Photos attached inline. Returns the created photo records; `errors` is null on success and `request` is empty because nothing was queued.
Response
{  "data": {    "addLocationPhotos": {      "clientMutationId": null,      "success": true,      "request": {},      "photos": [        {          "id": "TWVkaWFGaWxlOjU4Nzg5MzE=",          "databaseId": 5878931,          "url": "https://sy-media-store.s3-us-west-2.amazonaws.com/f868bb3f/59c670a3/f47d62a6.png",          "thumbnailUrl": "https://sy-media-store.s3-us-west-2.amazonaws.com/f868bb3f/59c670a3/thumbnail_f47d62a6.png",          "type": "LOGO",          "starred": false        },        {          "id": "TWVkaWFGaWxlOjU4Nzg5MzI=",          "databaseId": 5878932,          "url": "https://sy-media-store.s3-us-west-2.amazonaws.com/f868bb3f/59c670a3/ef4ffb12.jpg",          "thumbnailUrl": "https://sy-media-store.s3-us-west-2.amazonaws.com/f868bb3f/59c670a3/thumbnail_ef4ffb12.jpg",          "type": "ADDITIONAL",          "starred": false        }      ],      "errors": null    }  }}
401Unauthenticated, missing or invalid API key.

Attaches one or more images to a location. Supply a photos array where each item carries at least photo, a public image URL that Listings API fetches and stores. locationId and a non-empty photos array are always required.

Two shapes of success

A small batch uploads inline: photos carries the finished media and request is an empty object, as in the sample above. A large batch is queued instead, and the same 200 looks like this:

JSON
{  "data": {    "addLocationPhotos": {      "clientMutationId": null,      "success": true,      "request": {        "requestId": "e6c2d9d9-9a18-4015-88cf-9a4e19a6f49a",        "status": "PROCCESSING"      },      "photos": [],      "errors": null    }  }}

Both are successes, so handle them by testing whether request.requestId is present rather than by assuming photos is populated.

The URL field is photo. Not url, and not image. Alongside it each item accepts an optional type (LOGO, COVER, or ADDITIONAL), starred, and source; publisherOverride and partnerMediaId are also accepted for partner integrations. A returned photo has no caption field.

Use case: seed a new location's imagery. Right after creating a location such as "Jenny Home", POST its logo and storefront photos by URL in a single call. The response returns each new photo's id, which you pass to the star and remove endpoints later.

Use case: reuse an approved asset across locations. Point multiple locations at the same hosted image URL in their photos arrays so every location shares the same source asset.

Gotchas.

  • Images must be JPEG or PNG. Publisher size rules apply per category (a typical floor is ~10 KB and ceiling of a few MB).
  • Large batches are processed asynchronously. Above a server-side batch size, the call queues the work instead of uploading inline: photos comes back empty and request.requestId is set. Poll GET /locations/photos/requests/{requestId} with that id to track completion. The threshold is server-side configuration, so treat it as "large batches may be queued" rather than a fixed number, and branch on whether request.requestId is present.
  • Do not switch on request.status. On the queued response it is the literal string PROCCESSING, which is spelled differently from the PROCESSING the poll endpoint reports for the same job. request.requestId being present is the reliable signal.
  • Passing starred: true on more than the 4 allowed starred photos fails the whole call with SY15012. The check counts the location's existing starred photos plus the starred items in this request.
  • A location keeps a single logo and single cover; re-uploading either category replaces the existing image.
  • Set type explicitly when you mean an image to be the logo or cover. Without it the image is stored as an additional photo.
Request
curl -X POST 'https://listingsapi.com/api/v4/locations/photos' \  -H "Authorization: API $LISTINGSAPI_KEY" \  -H 'Content-Type: application/json' \  -d '{    "input": {      "locationId": "TG9jYXRpb246MTgwMDI4OQ==",      "photos": [        {          "photo": "https://cdn.example.com/jenny-home/logo.png",          "type": "LOGO"        },        {          "photo": "https://cdn.example.com/jenny-home/storefront.jpg",          "type": "ADDITIONAL"        }      ]    }  }'