Property media and public agents

Source-reviewed draft; deployment and release verification pending.

Draft — source-reviewed on 22 October 2026. Public media enablement and asset readiness in a deployed environment have not been verified.

Image DTOs

Search may include thumbnail with required string asset_id and url, plus optional nullable caption. Detail instead returns required gallery, up to 100 entries with those fields plus required boolean is_primary and integer display_order.

The selected order is primary images first, then display order and a deterministic tie-breaker. Use the returned ordering for initial gallery design. gallery: [] and an absent thumbnail are valid states. The placeholder caption UNKNOWN is omitted by the current projection.

{
  "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 invented gallery entry is for UI design. Resolve relative URLs against the approved API origin, not the ReadMe documentation origin. An asset UUID must remain bound to its public property URL; cross-property image access is rejected.

Safe derivative delivery

The public image endpoint serves a sanitized JPEG derivative, never an original-file fallback. Source processing orients and re-encodes pixels and removes inherited metadata, including EXIF/GPS and comments. Only ready derivatives are projected into gallery/thumbnail selections. Storage readiness can still change before the browser loads an image.

Successful image responses use image/jpeg, Cache-Control: no-store and X-Content-Type-Options: nosniff. Unavailable, unready, invalid or withdrawn assets return 404. Temporary dependency failure can return 503, and admission limits can return 429.

The wire contract has no derivative-set object, width/height array, original download URL, private storage key, video collection, virtual-tour field or document list. Do not manufacture those fields from the broader CRM media model, infer a storage URL from asset_id, or fall back to protected originals.

Use a skeleton while loading, a neutral image placeholder for an empty gallery and an image-local error state for failed downloads. Do not keep broken images cycling through rapid retries. Use captions safely as text and provide appropriate alt text when a caption is absent.

Public agent card

Detail may include agent. It is absent when there is no eligible public profile: for example no assigned agent, an inactive user, public visibility disabled or missing display name. Search summaries do not contain an agent card.

Public fieldBehavior
display_nameRequired string when the agent object is present.
photo_urlOptional nullable URL to the public agent-image endpoint.
public_phoneOptional nullable explicitly entered public phone.
public_emailOptional nullable explicitly entered public email.
whatsapp_phoneOptional nullable explicitly entered public WhatsApp phone.
preferred_contact_methodOptional nullable string preference.
preferred_contact_timeOptional nullable string preference.

Only explicitly public profile fields are projected. There is no fallback to a private account email, login name, user identifier or private profile photo. The photo must be current, unretired and owned by the profile holder. Detail selects the assigned agent's public profile. The standalone agent-image endpoint re-checks that the photo is current, unretired and owned by an active user with an enabled public profile; it does not re-check an assignment to a currently published property.

{
  "agent": {
    "display_name": "Example Agent",
    "public_email": "[email protected]",
    "preferred_contact_method": "EMAIL"
  }
}

This is a synthetic detail fragment, not a complete response. The current profile's controlled preferred contact values are PHONE, EMAIL and WHATSAPP, while the public response schema types the value as a string. Treat an unknown preference safely and do not assume every contact channel is present. Hide individual absent channels and omit the whole card if agent is absent/null. Sanitize URL construction for mailto:, tel: and WhatsApp actions rather than interpolating untrusted values as HTML.

Related operations

POST /api/v1/public/properties/search (thumbnail), GET /api/v1/public/properties/{public_id} (gallery and agent), GET /api/v1/public/properties/{public_id}/images/{asset_id} and GET /api/v1/public/agent-images/{asset_id}.


Did this page help you?