From Property to Listing

Five steps that can be fully automated - from an empty record to a published document.

EPC Disclosures Property Data

Step 1: Create a Property

A listing never comes out of nowhere - it always references a property. Create it first via Property Management.

curl -X POST https://api.realestateagency.example/v1/properties \
  -H "apikey: $REAL_ESTATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "type": "apartment",
        "title": "3-Bedroom Period Home near Riverside Park",
        "address": { "street": "148 Elm Street", "postal_code": "10001", "city": "Springfield" },
        "living_area_sqm": 86.5,
        "rooms": 3,
        "year_built": 1908,
        "purchase_price_eur": 645000,
        "commission": { "buyer_percent": 3.57, "note": "includes applicable sales tax" },
        "energy_certificate": {
          "type": "consumption",
          "final_energy_demand_kwh": 118.4,
          "energy_source": "district_heating",
          "efficiency_class": "D",
          "valid_until": "2031-04-30"
        }
      }'

The energy_certificate block is optional when creating a property, but mandatory for later publication. See Mandatory Disclosures.

Step 2: Upload Media

Photos and floor plans are attached to the property, not to a listing. That way they're available to every listing and template generated later.

curl -X POST https://api.realestateagency.example/v1/properties/prop_8f2c1a/media \
  -H "apikey: $REAL_ESTATE_API_KEY" \
  -F "file=@living-room.jpg" \
  -F "category=interior" \
  -F "order=1"

At least one cover photo (category=cover_photo) and one floor plan (category=floor_plan) are recommended. If the cover photo is missing, the template falls back to a neutral placeholder graphic.

Step 3: Generate a Listing

Want to see the flow without code first? The Listing Generator accepts the same property data through a form and produces a finished listing text via a language model - the call runs through the Kong AI Gateway.

curl -X POST https://api.realestateagency.example/v1/listings \
  -H "apikey: $REAL_ESTATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "property_id": "prop_8f2c1a",
        "template_id": "tpl_classic",
        "sections": ["location", "features", "energy", "floor_plan", "commission"]
      }'
{
  "id": "lst_4d9b2e",
  "property_id": "prop_8f2c1a",
  "template_id": "tpl_classic",
  "status": "in_progress",
  "created_at": "2026-08-20T09:41:12Z"
}

Generation is asynchronous because images need to be resized and the PDF laid out. Usually takes two to ten seconds.

Step 4: Retrieve the Result

Two paths lead to the finished document:

Event-driven (recommended). Subscribe to listing.completed; the webhook carries the listing ID and the download link. See Webhooks.

Polling. Poll GET /listings/{id} with increasing backoff (1s, 2s, 4s, 8s) until status reaches completed:

curl https://api.realestateagency.example/v1/listings/lst_4d9b2e/pdf \
  -H "apikey: $REAL_ESTATE_API_KEY" \
  -o listing-elm-street.pdf

The link in pdf_url is valid for 24 hours. Store the document instead of passing the link around.

Step 5: Publish

curl -X POST https://api.realestateagency.example/v1/listings/lst_4d9b2e/publish \
  -H "apikey: $REAL_ESTATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "channels": ["portal", "website", "newsletter"] }'

Before publishing, the API checks the mandatory disclosures. If something's missing, you get 422:

{
  "code": "mandatory_disclosure_missing",
  "message": "Mandatory disclosures from the energy certificate are missing for publication.",
  "details": [
    { "field": "energy_certificate.final_energy_demand_kwh", "reason": "missing" }
  ]
}

Add the missing figure on the property, regenerate the listing, and publish again. A listing that's already been generated is never changed after the fact - that keeps the history traceable.

Common Pitfalls

  • A listing with no property reference. property_id is required; standalone listings deliberately don't exist.
  • A template from a different tenant. template_id must belong to your tenant, otherwise 404.
  • PDF retrieved too early. Before status: "completed", /pdf returns 409.
  • Price change without regenerating. Updating a property doesn't automatically update existing listings.