Photos

Ajoutez logo, couverture et photos de galerie à un établissement, étoilez l’image principale et retirez les fichiers obsolètes via le SDK listingsapi-js.

Les photos sont associées à un établissement via une URL publique : vous hébergez l’image, la plateforme la récupère et la stocke, puis les plateformes de publication la récupèrent à leur tour. Un établissement conserve un logo, une image de couverture et un nombre illimité de photos supplémentaires, dont quatre au maximum peuvent être marquées d’une étoile. Toutes les méthodes de gestion des photos sont disponibles sur l’instance du client ListingsAPI et s’appliquent à un identifiant d’établissement. Les identifiants numériques des établissements sont encodés automatiquement ; 1800289 et 'TG9jYXRpb246MTgwMDI4OQ==' sont donc interchangeables.

Les envois réussis produisent deux types de réponses. Un petit lot est stocké immédiatement et la réponse contient les médias traités ; un lot volumineux est placé dans une file d’attente et vous recevez un identifiant de requête permettant d’interroger son état. Choisissez le traitement à effectuer selon la présence de request.requestId plutôt qu’en comptant vos images.

fetchLocationPhotos

Listez tous les fichiers multimédias associés à un établissement : logo, image de couverture et images supplémentaires. Appelez cette méthode avant un envoi pour voir ce qui manque et récupérer les identifiants des photos utilisés par les méthodes de marquage par étoile et de suppression.

TypeScript
const photos = await client.fetchLocationPhotos(1800289); for (const p of photos) {console.log(p.id, p.categoryName, p.starred, p.url);}

Paramètres

ParamètreTypeDescription
locationIdstring | numberÉtablissement dont vous souhaitez récupérer les photos.

La promesse est résolue avec le tableau mediaFilesOfLocation, qui est vide par défaut. Chaque fichier contient id, url, thumbnailUrl, categoryName (Logo, Cover ou Additional), categoryId, fileType, starred et viewsCount. Pour un établissement sans médias, un tableau vide est renvoyé : il s’agit de la réponse normale pour un établissement nouvellement créé, et non d’une erreur.

addLocationPhotos

Associez une ou plusieurs images à un établissement. Chaque élément doit fournir dans photo l’URL d’une image JPEG ou PNG accessible publiquement, ainsi que l’emplacement qu’elle occupe dans type.

TypeScript
const result = await client.addLocationPhotos(1800289, [{ photo: 'https://cdn.example.com/brightsmile/logo.png', type: 'LOGO' },{ photo: 'https://cdn.example.com/brightsmile/storefront.jpg', type: 'ADDITIONAL' },]); if (result.request?.requestId) {// Queued: poll fetchPhotoUploadStatus with this idconsole.log('queued', result.request.requestId);} else {for (const p of result.photos ?? []) {  console.log('stored', p.id, p.type);}}

Options des photos

ParamètreTypeDescription
photostringURL publique d’une image JPEG ou PNG que la plateforme récupère et stocke. Le champ est photo, et non url. Obligatoire.
type'LOGO' | 'COVER' | 'ADDITIONAL'Emplacement occupé par l’image. Obligatoire.
partnerMediaIdstringVotre propre identifiant du fichier, conservé avec celui-ci pour les intégrations partenaires.

Paramètres

ParamètreTypeDescription
locationIdstring | numberÉtablissement auquel associer les médias.
photosPhotoInput[]Images à associer. Ne doit pas être vide.

La promesse est résolue avec les données de addLocationPhotos : success, photos, request, errors et clientMutationId. Lors d’un envoi traité immédiatement, photos contient les nouveaux médias avec, pour chacun, id, databaseId, url, thumbnailUrl, type et starred, et request est un objet vide. Lors d’un envoi mis en file d’attente, photos est vide et request.requestId est renseigné. Les deux cas correspondent à une réussite.

Les images doivent être au format JPEG ou PNG, et les règles de taille des plateformes de publication s’appliquent à chaque emplacement. Un établissement conserve un seul logo et une seule image de couverture ; un nouvel envoi pour l’un ou l’autre remplace donc l’image existante. Définissez type avec soin : les images de la galerie doivent être placées dans ADDITIONAL.

fetchPhotoUploadStatus

Interrogez régulièrement l’état d’un envoi mis en file d’attente jusqu’à ce qu’il atteigne un état final. Utilisez le request.requestId renvoyé par addLocationPhotos.

TypeScript
let job = await client.fetchPhotoUploadStatus('e6c2d9d9-9a18-4015-88cf-9a4e19a6f49a'); while (job.status === 'PROCESSING') {await new Promise((resolve) => setTimeout(resolve, 5000));job = await client.fetchPhotoUploadStatus('e6c2d9d9-9a18-4015-88cf-9a4e19a6f49a');} for (const p of job.photos ?? []) {if (p.status === 'ERROR') {  console.log('rejected:', p.errorMessage);}}

Paramètres

ParamètreTypeDescription
requestIdstringIdentifiant de requête renvoyé par un appel à addLocationPhotos dont l’envoi a été mis en file d’attente.

Les données contiennent requestId, un champ status de la tâche valant PROCESSING, SUCCESS ou ERROR, ainsi qu’un tableau photos dont chaque entrée contient mediaId, locationId, sa propre valeur de status et un champ errorMessage.

Le champ status de la tâche indique que le traitement est terminé, et non que toutes les images ont été enregistrées. Une tâche à l’état SUCCESS peut encore contenir des photos rejetées ; dès qu’elle quitte l’état PROCESSING, parcourez donc photos et lisez chaque entrée. Attendez quelques secondes entre les interrogations : une boucle sans pause atteint rapidement la limite de requêtes. Interrogez uniquement les identifiants issus d’un envoi récent, car un identifiant expiré n’atteint jamais d’état final.

starLocationPhotos

Marquez les photos supplémentaires d’une étoile pour qu’elles soient affichées en priorité sur les plateformes de publication prenant en charge la mise en avant d’images, ou retirez leur étoile en passant false.

TypeScript
// Feature a photoconst result = await client.starLocationPhotos(1800289,['TWVkaWFGaWxlOjU4Nzg5MzI='],true,); console.log(result.success, result.photos[0].starred); // Reverse itawait client.starLocationPhotos(1800289, ['TWVkaWFGaWxlOjU4Nzg5MzI='], false);

Paramètres

ParamètreTypeDescription
locationIdstring | numberÉtablissement auquel les photos sont associées.
mediaIdsstring[]Identifiants des photos auxquelles ajouter ou retirer une étoile, issus de fetchLocationPhotos ou d’une réponse d’envoi. Transmis dans la requête sous photoIds.
starredbooleantrue pour marquer les photos indiquées d’une étoile, false pour leur retirer l’étoile.

La promesse est résolue avec les données de starUnstarLocationPhotos : success, photos et un objet error unique plutôt qu’un tableau errors. Chaque photo renvoyée contient id, databaseId, url, thumbnailUrl, type et sa nouvelle valeur de starred.

Seules les photos ADDITIONAL peuvent être marquées d’une étoile ; le logo et l’image de couverture sont déjà des images principales. Un établissement peut contenir au maximum quatre photos marquées d’une étoile, et la vérification compte celles qui le sont déjà ainsi que celles de votre appel ; dépasser quatre fait donc échouer toute la requête.

removeLocationPhotos

Dissociez des photos d’un établissement à l’aide de leurs identifiants. Utilisez cette méthode pour retirer des images obsolètes de la galerie ou annuler une importation incorrecte.

TypeScript
const result = await client.removeLocationPhotos(1800289, ['TWVkaWFGaWxlOjU4Nzg5MzI=',]); console.log(result.removedCount); // 1

Paramètres

ParamètreTypeDescription
locationIdstring | numberÉtablissement auquel les photos sont associées.
photoIdsstring[]Identifiants des photos à dissocier, issus de fetchLocationPhotos ou d’une réponse d’envoi.

La promesse est résolue avec les données de removeLocationPhotos : removedCount, errors et clientMutationId. Une valeur de removedCount égale à 0 avec un champ errors valant null signifie qu’aucun des identifiants envoyés n’était associé à cet établissement, ce qui vous permet de détecter les identifiants déjà absents.

Seules les photos ADDITIONAL peuvent être supprimées ici. Pour remplacer un logo ou une image de couverture, envoyez une nouvelle image. La suppression d’un média le dissocie de l’établissement ; elle ne supprime pas nécessairement le fichier de la bibliothèque multimédia du compte.

refresh_photos.ts
import { ListingsAPI } from 'listingsapi-js'; const client = new ListingsAPI(); // reads LISTINGSAPI_KEY from envconst LOCATION_ID = 1800289; // Brightsmile Dental // 1. See what is already attachedconst existing = await client.fetchLocationPhotos(LOCATION_ID);const hasLogo = existing.some((p) => p.categoryName === 'Logo'); // 2. Upload only what is missing, plus the new hero shotconst uploaded = await client.addLocationPhotos(LOCATION_ID, [...(hasLogo ? [] : [{ photo: 'https://cdn.example.com/brightsmile/logo.png', type: 'LOGO' as const }]),{ photo: 'https://cdn.example.com/brightsmile/hero-2026.jpg', type: 'ADDITIONAL' as const },]); // 3. Feature the new hero shotconst hero = (uploaded.photos ?? []).find((p) => p.type === 'ADDITIONAL');if (hero) {await client.starLocationPhotos(LOCATION_ID, [hero.id], true);} // 4. Retire last season's imagesconst stale = existing.filter((p) => p.categoryName === 'Additional' && !p.starred).map((p) => p.id);if (stale.length > 0) {const removed = await client.removeLocationPhotos(LOCATION_ID, stale);console.log('removed ' + removed.removedCount + ' stale photos');}