# Canonical Property Schema

The Developer API publishes the same flat canonical property model consumed by the Feed Engine for BLM, CSV and XML imports. The request envelope is:

```json
{
  "request_id": "req-001",
  "property": {
    "external_ref": "CRM-001",
    "department": "sale",
    "display_address": "10 High Street, London"
  }
}
```

Do not create a second nested property schema. Legacy nested aliases may be tolerated internally, but public integrations must use these canonical fields.

Requiredness:

- `Required` means required to accept a property request.
- `Live required` means required when `published` is true or `marketing_status` maps to a live state.
- `Optional` means imported when supplied.
- `System` means ownership/sync metadata normally derived by Quardlyn.

| Field | Type | Required | Allowed values | Description | Example |
|---|---:|---|---|---|---|
| `external_ref` | string | Required | Printable UTF-8, max 191, no path separators | Provider reference unique per authenticated connection. | `CRM-SALE-001` |
| `department` | string | Required | `sale`, `let`, `rent`, `auction`, `commercial` | Listing department imported to `uk_pfor`. | `sale` |
| `marketing_status` | string | Optional | `draft`, `available`, `under_offer`, `sold_stc`, `sold`, `let_agreed`, `let`, `withdrawn`, `archived` | Public listing state. | `available` |
| `published` | boolean | Optional | `true`, `false` | Imports as LIVE when true and live validation passes. | `true` |
| `status_id` | integer | Optional | `0` draft/default, `1` available, `2` under offer, `3` sold STC, `4` sold, `5` inactive | Feed status code. | `1` |
| `trans_type_id` | integer | Optional | `1` sale, `2` let, `3` auction, `4` commercial | Feed transaction type. | `1` |
| `category` | string | Optional | Provider category | Residential, commercial, land, new homes, student or shared ownership grouping. | `residential` |
| `title` | string | Optional | Any string | Public listing title; `display_address` remains required. | `Three-bedroom house near the station` |
| `display_address` | string | Required | Any string | Public display title/address. | `10 High Street, London` |
| `address_1`..`address_4` | string | Optional | Any string | Address lines. | `10 High Street` |
| `town` | string | Optional | Any string | Town/city. | `London` |
| `county` | string | Optional | Any string | County/area. | `Greater London` |
| `country` | string | Optional | Any string | Country; defaults internally to United Kingdom. | `United Kingdom` |
| `postcode` | string | Live required | UK postcode text | Full postcode. | `SW1A 1AA` |
| `postcode1`, `postcode2` | string | Optional | Postcode components | Split postcode fields used by feeds. | `SW1A`, `1AA` |
| `latitude`, `longitude` | number | Optional | Decimal coordinates | Public coordinate fields. | `51.501`, `-0.141` |
| `lat`, `lng` | number | Optional | Decimal coordinates | Feed-engine coordinate aliases. | `51.501`, `-0.141` |
| `property_type` | string/integer | Optional | Internal type id or label | Main property type/category. | `Residential Property` |
| `property_subtype` | string/integer | Optional | Internal subtype id or provider subtype | Subtype resolved by import mapping. | `101` |
| `property_sub_type` | string/integer | Optional | Internal subtype id or provider subtype | Alternate canonical subtype spelling accepted by the API. | `terraced` |
| `beds`, `baths`, `receptions` | integer | Optional | `0+` | Room counts. | `3` |
| `bedrooms`, `bathrooms` | integer | Optional | `0+` | Room count aliases accepted by the API. | `3`, `2` |
| `price` | number/string | Live required | Number or `POA` style value | Sale price, rent amount or auction guide price. | `525000` |
| `sale_price`, `rent_price`, `auction_price` | number/string | Optional | Amount or provider value | Transaction-specific price fields for feeds that separate price by department. | `525000`, `1650`, `300000` |
| `currency` | string | Optional | Currency code/label | Currency associated with price fields. | `GBP` |
| `price_display` | string | Optional | Any string | Display price fallback. | `Offers over GBP 525,000` |
| `price_qualifier` | string | Optional | Provider qualifier | Price qualifier. | `offers_over` |
| `tenure`, `tenure_type_id` | string/integer | Optional | `Freehold`, `Leasehold`, `1`, `2`, labels | Sale/auction tenure. | `1` |
| `new_home_flag` | boolean/integer/string | Optional | `true`, `false`, `1`, `0`, labels | New home/new build flag. | `false` |
| `new_build` | boolean/integer/string | Optional | `true`, `false`, `1`, `0`, labels | New build alias accepted by the API. | `false` |
| `furnished` | boolean/integer/string | Optional | Furnishing labels/codes | Lettings furnishing state. | `Furnished` |
| `leasehold_years` | number/string | Optional | `0+` | Remaining lease length. | `998` |
| `service_charge` | number/string | Optional | Amount | Service charge. | `1200` |
| `ground_rent` | number/string | Optional | Amount | Ground rent. | `250` |
| `council_tax_band` | string | Optional | Council tax band | Council tax band. | `D` |
| `epc_rating`, `epc_current_rating`, `epc_potential_rating` | string | Optional | EPC labels | EPC rating fields. | `C`, `C`, `B` |
| `parking`, `garage`, `garden`, `balcony`, `lift`, `accessibility` | string/boolean | Optional | Provider values | Amenity and accessibility fields. | `Driveway`, `Rear garden`, `Lift access` |
| `rent_frequency` | string/integer | Optional | `PCM`, `PW`, `pcm`, `pw`, `1`, `2` | Lettings rent period. Defaults to PCM for lettings. | `PCM` |
| `deposit` | number/string | Optional | Amount | Lettings deposit/bond. | `1673` |
| `available_from` | date string | Optional | `YYYY-MM-DD` | Lettings availability date. | `2026-08-01` |
| `let_min_term` | string | Optional | `1 month`..`12+ months`, label | Lettings minimum term. | `12+ months` |
| `let_type_id` | integer/string | Optional | `1` Long term, `2` Short term, `3` Student, labels | Lettings type. | `1` |
| `let_furn_id` | integer/string | Optional | `1` Unfurnished, `2` Furnished, `3` Part Furnished, labels | Furnishing state. | `2` |
| `size_min`, `size_max` | number | Optional | `0+` | Commercial or land area. | `1800` |
| `area_size_unit_id` | string/integer | Optional | `1`, `2`, `sqft`, `sq ft`, `sqm`, `sq m`, labels | Area unit. | `sqft` |
| `price_per_unit` | number | Optional | `0+` | Commercial/land price per unit. | `18` |
| `floor_area`, `floor_area_unit` | number/string | Optional | Area and unit | Floor area. | `1200`, `sqft` |
| `plot_area`, `plot_area_unit` | number/string | Optional | Area and unit | Plot or land area. | `0.25`, `acres` |
| `summary` | string | Optional | Any string | Short description. | `Three-bedroom house near local amenities.` |
| `description` | string | Optional | Any string | Full description. | `A well-presented property.` |
| `features` | string/array | Optional | Pipe string, double-pipe string or array | Feature list imported to extra features. | `["Garden", "Driveway"]` |
| `media_image_00`..`media_image_69` | string | Optional | URL or filename | Canonical image slots. `media_image_00` is primary. | `https://cdn.example.com/front.jpg` |
| `media_image_text_00`..`media_image_text_69` | string | Optional | Any string | Image captions/labels. | `Front elevation` |
| `image_0`..`image_10` | string | Optional | URL or filename | Legacy canonical image slots accepted by import mappings. Prefer `media_image_00`..`69`. | `https://cdn.example.com/front.jpg` |
| `image_caption_0`..`image_caption_10` | string | Optional | Any string | Legacy image captions. | `Front elevation` |
| `media_floorplan_00`..`media_floorplan_19` | string | Optional | URL or filename | Floorplan media slots. | `https://cdn.example.com/floorplan.jpg` |
| `floorplan` | string | Optional | URL or filename | Legacy floorplan alias. Prefer `media_floorplan_00`. | `https://cdn.example.com/floorplan.jpg` |
| `epc_image` | string | Optional | URL or filename | EPC image. | `https://cdn.example.com/epc.jpg` |
| `epc_pdf` | string | Optional | URL or filename | EPC PDF document. | `https://cdn.example.com/epc.pdf` |
| `brochure_pdf` | string | Optional | URL or filename | Brochure PDF document. | `https://cdn.example.com/brochure.pdf` |
| `media_document_00`..`media_document_19` | string | Optional | URL or filename | Generic document slots. | `https://cdn.example.com/terms.pdf` |
| `media_document_text_00`..`media_document_text_19` | string | Optional | Any string | Document labels. | `Terms` |
| `media_document_00_is_epc`..`media_document_19_is_epc` | boolean/integer/string | Optional | Provider flag | Marks a document slot as EPC-related when supplied by a feed. | `true` |
| `virtual_tour_url` | string | Optional | HTTPS URL | Normalized virtual tour URL. Preferred field for CRM/API/feed imports. | `https://my.matterport.com/show/?m=abc123` |
| `virtual_tour_provider` | string | System/Optional | `Matterport`, `EyeSpy360`, `YouTube`, `Vimeo`, `Kuula`, `Generic`, `Uploaded Video` | Detected automatically from `virtual_tour_url` unless supplied by trusted internal tools. | `Matterport` |
| `virtual_tour` | string | Optional | URL | Legacy virtual tour alias. Mapped into `virtual_tour_url`. | `https://tours.example.com/CRM-SALE-001` |
| `video` | string | Optional | URL | Video URL. | `https://video.example.com/CRM-SALE-001` |
| `source_type` | string | System | Provider key | Ownership/source metadata. | `GENERIC_CRM` |
| `feed_connection_id` | integer | System | Connection id | Owning feed/API connection. | `123` |
| `external_property_id` | string | System | Any string | Stored external reference mirror. | `CRM-SALE-001` |
| `managed_mode` | string | System | `CRM_MASTER`, `HYBRID`, `PORTAL_MASTER` | Field ownership mode. | `CRM_MASTER` |
| `last_sync_at` | date-time string | System | ISO 8601 | Last sync timestamp. | `2026-07-01T12:00:00Z` |
| `sync_status` | string | System | `OK`, `UNSEEN`, `MISSING`, provider states | Sync state. | `OK` |
| `sync_error` | string/null | System | Any string/null | Last sync error. | `null` |
| `seen_in_run_id` | integer/null | System | Feed run id/null | Feed run visibility marker. | `456` |
| `owner_id`, `owner_type`, `owner_name` | string | System | Provider/Quardlyn ownership values | Ownership identity metadata. | `crm-branch-1` |
| `field_owner`, `field_owner_map`, `ownership_source` | string/object | System | Ownership values | Field ownership metadata for CRM/portal conflict handling. | `CRM_MASTER` |
| `last_seen_at`, `source_updated_at` | date-time string | System | ISO 8601 | Sync visibility/source timestamps. | `2026-07-01T12:00:00Z` |
| `uprn` | string | Optional | UPRN | Unique Property Reference Number. | `100023336956` |
| `what3words` | string | Optional | What3Words address | Location helper field. | `filled.count.soap` |
| `portal_url` | string | Optional | URL | Source or public portal URL. | `https://example.com/property/CRM-001` |
| `seo_title`, `seo_description` | string | Optional | Any string | SEO metadata. | `Three-bedroom house for sale in London` |
| `floor_level` | string | Optional | Provider value | Floor level for flats/commercial units. | `2` |
| `rooms` | string/object | Optional | Provider value | Room data supplied by a CRM/feed. | `Living room 4.2m x 3.8m` |
| `flood_risk` | string | Optional | Provider value | Flood-risk notes. | `Low` |
| `material_information` | string/object | Optional | Provider value | Material information summary supplied by the CRM/feed. | `Mains water, mains drainage` |

## Request Example

```json
{
  "request_id": "auction-create-001",
  "property": {
    "external_ref": "CRM-AUC-001",
    "department": "auction",
    "marketing_status": "available",
    "status_id": 1,
    "trans_type_id": 3,
    "published": true,
    "display_address": "Auction Property, 4 Station Road, York",
    "address_1": "4 Station Road",
    "town": "York",
    "postcode": "YO1 1AA",
    "price": 300000,
    "price_qualifier": "guide_price",
    "property_type": "Residential Property",
    "property_subtype": 101,
    "beds": 3,
    "summary": "Auction property with vacant possession.",
    "description": "Guide price sale by auction.",
    "media_image_00": "https://cdn.example.com/auction/front.jpg",
    "epc_pdf": "https://cdn.example.com/auction/epc.pdf"
  }
}
```

## Response Example

```json
{
  "success": true,
  "request_id": "auction-create-001",
  "external_ref": "CRM-AUC-001",
  "status": "created",
  "message": "Property created successfully.",
  "warnings": []
}
```
