Read a Location's Google Photos from Stored Data
List the Google Business Profile photos Synup has stored for a location, owner and customer, with freshness and paging, without calling Google.
Auf einen Blick
- Was diese Anleitung leistet
- List a location's stored owner and customer Google photos, page through them, and read how fresh the data is.
- Verwendete APIs
- get
/api/v1/locations/{id}/media/googleGespeicherte Google-Fotos eines Standorts auflisten - get
/api/v1/media/googleGespeicherte Google-Fotos auflisten - get
/api/v1/mediaStandort-Medien abrufen - post
/api/v1/locations/{id}/mediaFotos zu einem Standort hochladen
- get
- Referenz
- MediaLocations
- Voraussetzungen
- An API key with the media:read scope
- A location id (loc_...), from the locations endpoints
- Typische Anwendungsfälle
- Showing a location's Google photos in your own dashboard
- Checking which photos customers added to a listing
- Telling a stale photo list from a complete one
Google-Fotos erreichen Sie auf zwei Wegen, und es sind nicht dieselben Daten. GET /api/v1/media liefert die eigene Mediathek von Synup für einen Standort, nach Kategorie gruppiert. Die beiden Endpunkte in dieser Anleitung, GET /api/v1/locations/{id}/media/google und GET /api/v1/media/google, liefern die Fotos, die Synup von Google selbst gespeichert hat: die vom Unternehmen hochgeladenen (owner) und die von Kunden hinzugefügten (ugc).
Beide Abrufe lesen nur Gespeichertes. Sie rufen Google nie auf und starten keine Synchronisierung, Sie können sie also gefahrlos wiederholt abfragen. Jedes Foto ist ein Verweis auf eine bei Google gehostete URL, keine Kopie (ein von Synup gesendetes Foto kann seine Quell-URL behalten, bis der nächste geplante Abruf sie durch die von Google ersetzt), und seine externalId (der vollständige Google-Ressourcenname) ist seine Identität: dieselbe URL unter zwei verschiedenen IDs sind zwei Fotos.
Erst Unternehmensfotos lesen, dann Kundenfotos, dann die nächste Seite
IDs, Namen und der Cursor in diesen Beispielen sind frei erfunden und nur zur Veranschaulichung, nicht ausführbar: Übergeben Sie immer den tatsächlichen nextCursor aus Ihrer eigenen Antwort. Beginnen Sie mit den eigenen Fotos des Unternehmens, eines pro Seite, damit der Seitenwechsel sichtbar wird.
curl "https://ai.synup.com/api/v1/locations/loc_456/media/google?kind=owner&limit=1" \
-H "Authorization: Bearer $SYNUP_API_KEY"{
"data": {
"items": [
{
"id": "9b2e7c14-5d3a-4f6e-8a21-c0d7f3a1b645",
"associationKey": "9b2e7c14-5d3a-4f6e-8a21-c0d7f3a1b645:loc_456",
"externalId": "accounts/102938475610293847561/locations/5647382910563748291/media/AF1QipOwnerLobby01",
"url": "https://lh3.googleusercontent.com/p/AF1QipOwnerLobby01",
"category": "INTERIOR",
"format": "PHOTO",
"kind": "owner",
"lastSeenAt": "2026-10-12T04:01:58.000Z",
"presence": "seen_in_last_complete_scan",
"moderation": { "status": null },
"location": { "id": "loc_456", "name": "Acme Dental, Downtown", "clientId": "cli_123" },
"freshness": { "coverage": "complete", "outcome": "complete", "lastAttemptAt": "2026-10-12T04:02:11.000Z", "lastSuccessAt": "2026-10-12T04:02:11.000Z", "completedScanAt": "2026-10-12T04:01:58.000Z" }
}
],
"location": {
"id": "loc_456", "name": "Acme Dental, Downtown", "clientId": "cli_123",
"owner": { "coverage": "complete", "outcome": "complete", "lastAttemptAt": "2026-10-12T04:02:11.000Z", "lastSuccessAt": "2026-10-12T04:02:11.000Z", "completedScanAt": "2026-10-12T04:01:58.000Z" },
"ugc": { "coverage": "unavailable", "outcome": "unavailable", "lastAttemptAt": "2026-10-12T04:02:12.000Z", "lastSuccessAt": null, "completedScanAt": null }
},
"limit": 1,
"nextCursor": "NEXT_CURSOR_FROM_THIS_RESPONSE"
}
}Der Block location kommt bei jedem Standortabruf zurück, auch ohne Einträge, und enthält die Aktualität von Unternehmens- und Kundenfotos. Jetzt die Kundenfotos.
curl "https://ai.synup.com/api/v1/locations/loc_456/media/google?kind=ugc" \
-H "Authorization: Bearer $SYNUP_API_KEY"{
"data": {
"items": [],
"location": {
"id": "loc_456", "name": "Acme Dental, Downtown", "clientId": "cli_123",
"owner": { "coverage": "complete", "outcome": "complete", "lastAttemptAt": "2026-10-12T04:02:11.000Z", "lastSuccessAt": "2026-10-12T04:02:11.000Z", "completedScanAt": "2026-10-12T04:01:58.000Z" },
"ugc": { "coverage": "unavailable", "outcome": "unavailable", "lastAttemptAt": "2026-10-12T04:02:12.000Z", "lastSuccessAt": null, "completedScanAt": null }
},
"limit": 50,
"nextCursor": null
}
}Eine leere Liste items bedeutet hier nicht „keine Kundenfotos“. ugc.coverage ist unavailable, Google hat beim letzten Versuch also nicht für Kundenfotos geantwortet. Lesen Sie location, bevor Sie einem Kunden eine leere Galerie zeigen. Folgen Sie zuletzt nextCursor von der ersten Seite, mit denselben Filtern.
curl "https://ai.synup.com/api/v1/locations/loc_456/media/google?kind=owner&limit=1&cursor=NEXT_CURSOR_FROM_THIS_RESPONSE" \
-H "Authorization: Bearer $SYNUP_API_KEY"{
"data": {
"items": [
{
"id": "c5d0e3a7-81b4-4a29-b6f2-3e9a7d1c0f58",
"associationKey": "c5d0e3a7-81b4-4a29-b6f2-3e9a7d1c0f58:loc_456",
"externalId": "accounts/102938475610293847561/locations/5647382910563748291/media/AF1QipOwnerFront02",
"url": "https://lh3.googleusercontent.com/p/AF1QipOwnerFront02",
"category": "EXTERIOR",
"format": "PHOTO",
"kind": "owner",
"lastSeenAt": "2026-10-12T04:01:58.000Z",
"presence": "seen_in_last_complete_scan",
"moderation": { "status": null },
"location": { "id": "loc_456", "name": "Acme Dental, Downtown", "clientId": "cli_123" },
"freshness": { "coverage": "complete", "outcome": "complete", "lastAttemptAt": "2026-10-12T04:02:11.000Z", "lastSuccessAt": "2026-10-12T04:02:11.000Z", "completedScanAt": "2026-10-12T04:01:58.000Z" }
}
],
"location": { "id": "loc_456", "...": "same location block as the first page" },
"limit": 1,
"nextCursor": null
}
}nextCursor ist null, das war also die letzte Seite. Ein Cursor funktioniert nur mit den Filtern, für die er ausgestellt wurde. limit nimmt eine ganze Zahl von 1 bis 100 an (Standard 50), jeder andere Wert ergibt ein 400 und wird nicht angepasst. Für alle Standorte auf einmal rufen Sie GET /api/v1/media/google auf, das auch locationId, clientId und kind annimmt; sein location ist nur null, wenn Sie kein locationId übergeben; mit locationId enthält es die Abdeckung dieses Standorts, auch wenn items leer ist. Jeder Eintrag trägt zusätzlich seinen eigenen.
Was die Felder zusichern
- Ein Eintrag pro Foto und Standort. Ein Foto, das mehrere Standorte teilen, erscheint einmal für jeden Standort, auf den Sie zugreifen dürfen. Identifizieren Sie Zeilen über
associationKey, nicht überid. presenceist eine Beobachtung.seen_in_last_complete_scanheißt, dass eine Antwort von Google das Foto enthielt, seit der letzte vollständige Scan begann.not_seen_in_last_complete_scanheißt, dass es in diesem Scan nicht enthalten war. Keines von beiden besagt, dass Google etwas gelöscht hat, undunknownheißt, dass es keinen vollständigen Scan zum Vergleichen gibt. Ein Foto, das Sie nach Beginn eines Scans gesendet haben, zählt ebenfalls als gesehen.- Nichts wird ausgeblendet. Als
spamoderneeds_reviewinmoderation.statusmarkierte Fotos werden weiterhin zurückgegeben, und alte Zeilen bleiben erhalten statt gefiltert zu werden. Wenden Sie Ihre eigene Regel an. - Zugriff begrenzt, was Sie sehen. Ein auf bestimmte Kunden beschränkter Schlüssel sieht nur deren Standorte, ein Standort ohne Kunde ist nur für agenturweite Schlüssel sichtbar, und die anderen Standorte eines geteilten Fotos werden nie zurückgegeben oder gezählt.
- Die Aktualität ist ehrlich. Eine erfolgreiche Aktualisierung wird alle 72 Stunden von einem täglichen Dispatcher um 04:00 UTC eingeplant. Eine fehlende Google-Verbindung oder ein Fehler erscheint als Abdeckung
partialoderunavailable, und ein 403 oder 404 von Google für Kundenfotos kann nicht verfügbar bedeuten, nicht leer. Dass ein erneuter Versuch zulässig ist, verspricht nicht, dass er in diesem Moment läuft.
Aus einem KI-Client (MCP)
Das Tool list_google_location_media liest dieselben gespeicherten Daten mit denselben Filtern (locationId, clientId, kind, limit, cursor) und liefert dieselbe Seite.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_google_location_media",
"arguments": { "locationId": "loc_456", "kind": "owner", "limit": 25 }
}
}Es aktualisiert nichts. fetch_gbp_media ist ein anderes Tool: Es ruft Google auf Anfrage ab und ändert gespeicherte Daten, nutzen Sie es also nur, wenn Sie einen neuen Abruf wollen.