Loading public media
Source-reviewed draft; deployment and release verification pending.
Draft — source-reviewed on 22 October 2026. Media storage, enabled capabilities and live delivery have not been verified. All asset identifiers and examples below are invented.
Thumbnail and gallery contracts
Search summaries may include thumbnail; detail requires gallery, which may be empty and contains up to 100 public images. Detail does not have a thumbnail field. A thumbnail has required string asset_id and url, plus optional nullable caption. Gallery entries add required is_primary and display_order.
{
"asset_id": "11111111-1111-4111-8111-111111111111",
"url": "/api/v1/public/properties/P9001/images/11111111-1111-4111-8111-111111111111",
"caption": "Example terrace",
"is_primary": true,
"display_order": 1
}This is a synthetic gallery entry for synthetic property P9001, not a complete property response. Keep the returned order: primary first, then display order with a deterministic tie-breaker. Do not infer dimensions, alternative sizes, video, original-image URLs, srcset candidates or a separate derivative object; these are not supplied by the public DTO.
Use asset_id as a stable component key within the current gallery. An absent/null caption is valid; the source placeholder UNKNOWN is omitted. Use a neutral accessible fallback when caption is missing. Preserve the difference between absent thumbnail, empty gallery and a failed network image.
Resolve and deliver URLs
Resolve relative URLs against the approved public API origin supplied during environment handoff, not against the ReadMe documentation site. No deployment origin is verified in this draft. A conceptual URL-resolution snippet is:
// API_ORIGIN is approved deployment configuration, not a CRM/private origin.
const mediaUrl = new URL(image.url, API_ORIGIN).toString();
// Use the supplied public URL; never derive a storage key or original URL.GET /api/v1/public/properties/{public_id}/images/{asset_id} checks current property eligibility, asset-to-property binding and approved derivative availability. A UUID from another property is not a reusable image identifier under this URL. Missing, retired, private, unapproved, unavailable or disabled media returns 404. Do not recover it through another API or a private storage path.
The server serves approved sanitized derivatives, not protected originals. Local and private object-storage handling are server concerns. There is no public storage path in the response. Frontend developers must not construct bucket URLs or attach private credentials to public media requests.
Public agent photographs
Detail's optional agent.photo_url points to GET /api/v1/public/agent-images/{asset_id}. The whole agent can be absent/null; an existing public profile may still have no photo. Hide the image or use a neutral avatar in those states. Do not substitute a private user image.
The standalone photo endpoint verifies that the photo is current, unretired and owned by an active user with an enabled public profile. It does not require an assignment to a currently published property. Withdrawing a listing therefore does not revoke an otherwise eligible public agent photograph. See Rendering property details for contact opt-in behavior.
Gallery interaction and failure states
Reserve visual space while images load to avoid layout jumps. Provide keyboard-operable next/previous controls, visible focus and meaningful button names. A lightbox is a proposed UI component, not an API object. Keep its selected index local to the current gallery and reset it when the property changes. Never assume gallery items are all successfully loadable because detail JSON arrived.
On an empty gallery show a neutral placeholder; on a failed image show an unavailable tile without a retry loop. Handle API/media-disabled 404, throttling 429 and temporary 503 separately where response status is available. Respect Retry-After and use bounded manual retry. Do not expose internal response text in alt labels or UI errors. A failed optional photo should not hide otherwise usable public detail.
Successful public JSON/image responses and handled errors within the public request boundary use Cache-Control: no-store. The outer application exception boundary returns {"detail":"Internal Server Error"} for unexpected 500 responses but may omit this header. As defensive client behavior, tolerate unreadable infrastructure failures without displaying raw response text. Avoid service worker/CDN caching and permanent local media copies even if an unexpected failure lacks cache headers. Already displayed bytes cannot be remotely erased; subsequent endpoint checks are the server's withdrawal boundary. Never promise that a public derivative reveals an exact location or contains private originals.
Related operations
Select media through POST /api/v1/public/properties/search or GET /api/v1/public/properties/{public_id}; fetch bytes through GET /api/v1/public/properties/{public_id}/images/{asset_id} and GET /api/v1/public/agent-images/{asset_id}. GET /api/v1/public/property-reference supplies controlled metadata, not image assets. See Property media and public agents.
Updated 1 day ago