# Prop360 Integration API Documentation

## Overview

The Prop360 Integration API allows external applications to create, read, update, and delete properties in the Prop360 system using API tokens. The API uses user-friendly field names instead of internal field IDs, making it easier for external developers to work with the system.

## Authentication

All API requests must include an API token in the Authorization header:

```
Authorization: Bearer YOUR_API_TOKEN
```

API tokens are generated by prop360 administrators and are associated with specific brokers/agents.

## Base URL

```
https://your-domain.com/api/integration
```

## Endpoints

### 1. Get Available Fields

**GET** `/fields`

Returns the list of available fields for the merchant, including user-friendly names and field types.

**Response:**
```json
{
  "success": true,
  "fields": [
    {
      "fieldId": "property_title",
      "userFriendlyName": "Property Title",
      "type": "text",
      "required": true,
      "options": null
    },
    {
      "fieldId": "property_type",
      "userFriendlyName": "Property Type",
      "type": "select",
      "required": true,
      "options": [
        { "label": "Apartment", "value": "apartment" },
        { "label": "House", "value": "house" },
        { "label": "Villa", "value": "villa" }
      ]
    }
  ]
}
```

### 2. List Properties

**GET** `/properties`

Returns a paginated list of properties for the merchant.

**Query Parameters:**
- `page` (optional): Page number (default: 1)
- `limit` (optional): Items per page (default: 10)

**Response:**
```json
{
  "success": true,
  "properties": [
    {
      "id": "507f1f77bcf86cd799439011",
      "pid": 1,
      "data": {
        "Title": "Beautiful 3-bedroom apartment",
        "Type": "apartment",
        "Price": 250000,
        "Bedrooms": 3,
        "Bathrooms": 2,
        "isPublic": true
      },
      "isPublic": true,
      "createdAt": "2024-01-15T10:30:00Z",
      "updatedAt": "2024-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 25,
    "pages": 3
  }
}
```

### 3. Get Property

**GET** `/properties/{id}`

Returns a specific property by ID.

**Response:**
```json
{
  "success": true,
  "property": {
    "id": "507f1f77bcf86cd799439011",
    "pid": 1,
          "data": {
        "Title": "Beautiful 3-bedroom apartment",
        "Type": "apartment",
        "Price": 250000,
        "Bedrooms": 3,
        "Bathrooms": 2,
        "isPublic": true
      },
    "isPublic": true,
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
}
```

### 4. Create Property

**POST** `/properties`

Creates a new property.

**Request Body:**
```json
{
  data: {
    Title: 'Luxury Villa',
    Category: 'Residential',
    Status: 'Sale',
    Price: 250000,
    'Construction Year': 2020,
    Floor: '1',
    Type: 'Apartment',
    Bedroom: 3,
    Bathrooms: 2,
    'Square Meters': 150,
    'Year Built': 2020,
    ParkingSpaces: 3,
    Garden: true,
    Pool: true,
    WC: 2,
    Description: 'A luxurious apartment with amazing views',
    Availability: 'Available',
    'Building Floors': 2,
    Levels: '1',
    Renovated: 'Yes',
    'Renovation Year': 2021,
    Appliances: 'Yes',
    Furnished: 'Yes',
    'Living Room': 5,
    'Energy Class': 'A',
    'Heating System': 'Central',
    'Heating Type': 'Gas',
    'Cooling System': 'Central',
    'Outdoor Parking': '1',
    'Indoor Parking': '2',
    Balcony: 'Yes',
    Elevator: 'Yes',
    Storage: 'Yes',
    'Golden Visa Compliant': 'Yes',
    Garden: 'Yes',
    Pool: 'No',
    Address: '123 Main St',
    'Postal Code': '12345',
    // Hierarchical Location Fields - Provide at least one level
    Region: {
      id: 104,
      name: "Τήνος",
      nameEN: "Tinos"
    },
    SubRegion: {
      id: 2402,
      name: "Υστέρνια", 
      nameEN: "Ysternia"
    },
    Area: {
      id: 123304,
      name: "Δέση",
      nameEN: "Desi"
    },
    // Alternatively, you can provide just IDs and names will be resolved automatically
    // Region: 104,
    // SubRegion: 2402,
    // Area: 123304,
    Location: {
      lat: 34.1328808,
      lng: -80.87771959999999,
    },
    isPublic: true,
  },

}
```

**Response:**
```json
{
  "success": true,
  "property": {
    "id": "507f1f77bcf86cd799439012",
    "pid": 2,
    "data": {
      "Title": "New Property",
      "Type": "house",
      "Price": 350000,
      "Bedrooms": 4,
      "Bathrooms": 3,
      "Description": "A beautiful family home",
      "Location": {
        "lat": 37.9838,
        "lng": 23.7275
      },
      "isPublic": true
    },
    "isPublic": true,
    "createdAt": "2024-01-15T11:00:00Z",
    "updatedAt": "2024-01-15T11:00:00Z"
  }
}
```

### 5. Update Property

**PUT** `/properties/{id}`

Updates an existing property.

**Request Body:**
```json
{
  "data": {
    "Title": "Updated Property Title",
    "Price": 375000,
    "Location": {
      "lat": 38.1234,
      "lng": 23.9876
    },
    "isPublic": false
  }
}
```

**Response:**
```json
{
  "success": true,
  "property": {
    "id": "507f1f77bcf86cd799439011",
    "pid": 1,
    "data": {
      "Title": "Updated Property Title",
      "Type": "apartment",
      "Price": 375000,
      "Bedrooms": 3,
      "Bathrooms": 2,
      "Location": {
        "lat": 38.1234,
        "lng": 23.9876
      },
      "isPublic": false
    },
    "isPublic": false,
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T11:30:00Z"
  }
}
```

### 6. Delete Property

**DELETE** `/properties/{id}`

Deletes a property (soft delete).

**Response:**
```json
{
  "success": true,
  "message": "Property deleted successfully"
}
```

### 7. Upload Images

**POST** `/properties/{id}/images`

Uploads images to a property.

**Request:**
- Content-Type: `multipart/form-data`
- Body: Form data with `images` field containing one or more image files

**Response:**
```json
{
  "success": true,
  "message": "3 images uploaded successfully",
  "images": [
    {
      "originalName": "property1.jpg",
      "fileName": "property-507f1f77bcf86cd799439011-1705312800000-abc123.jpg",
      "fileType": "image/jpeg",
      "fileSize": 2048576,
      "url": "https://your-storage-domain.com/uploads/property-507f1f77bcf86cd799439011-1705312800000-abc123.jpg",
      "key": "uploads/property-507f1f77bcf86cd799439011-1705312800000-abc123.jpg"
    }
  ],
  "totalImages": 5
}
```

## Important Fields

### isPublic Field
The `isPublic` field controls the visibility of the property:
- **Location**: Inside the `data` object
- **Type**: Boolean (`true`/`false`)
- **Purpose**: Determines if the property is publicly visible
- **Default**: `false` if not specified

**Example:**
```json
{
  "data": {
    "Title": "My Property",
    "Price": 250000,
    "isPublic": true
  }
}
```

### Hierarchical Location Fields (UPDATED)
Instead of using simple `City` field, the API now supports hierarchical location fields that store structured geographic data:

- **Fields**: `Region`, `SubRegion`, `Area`
- **Requirement**: At least one level must be provided
- **Storage**: Stored in `area_hierarchy_level_1` complex field
- **Format**: Object with `id`, `name`, and `nameEN` properties or simple ID value

**Supported Field Names:**
- `Region` or `region` - Level 1 (Country/Region)
- `SubRegion` or `sub-region` or `subregion` - Level 2 (State/Province)
- `Area` or `area` - Level 3 (City/Municipality)

**Complete Object Format:**
```json
{
  "data": {
    "Title": "My Property",
    "Price": 250000,
    "Region": {
      "id": 104,
      "name": "Τήνος",
      "nameEN": "Tinos"
    },
    "SubRegion": {
      "id": 2402,
      "name": "Υστέρνια",
      "nameEN": "Ysternia" 
    },
    "Area": {
      "id": 123304,
      "name": "Δέση",
      "nameEN": "Desi"
    },
    "isPublic": true
  }
}
```

**Simple ID Format (names auto-resolved):**
```json
{
  "data": {
    "Title": "My Property",
    "Price": 250000,
    "Region": 104,
    "SubRegion": 2402,
    "Area": 123304,
    "isPublic": true
  }
}
```

**Minimum Required (at least one level):**
```json
{
  "data": {
    "Title": "My Property",
    "Price": 250000,
    "Region": 104,
    "isPublic": true
  }
}
```

### Map/Location Fields
Map fields store geographic coordinates:
- **Location**: Inside the `data` object
- **Type**: Object with `lat` and `lng` properties
- **Purpose**: Store property location coordinates
- **Format**: Decimal degrees (not degrees/minutes/seconds)

**Example:**
```json
{
  "data": {
    "Title": "My Property",
    "Price": 250000,
    "Region": 104,
    "Location": {
      "lat": 37.9838,
      "lng": 23.7275
    },
    "isPublic": true
  }
}
```

**Valid Location Examples:**
```json
// Athens, Greece
"Location": {
  "lat": 37.9838,
  "lng": 23.7275
}

// London, UK
"Location": {
  "lat": 51.5074,
  "lng": -0.1278
}

// New York, USA
"Location": {
  "lat": 40.7128,
  "lng": -74.0060
}
```

### Property IDs
Properties have two types of identifiers:

1. **`id`** (MongoDB ObjectId): Used for API operations
   - Format: 24-character hexadecimal string
   - Example: `"507f1f77bcf86cd799439011"`
   - Usage: API endpoints, database queries

2. **`pid`** (Property ID): Used for public URLs
   - Format: Numeric identifier
   - Example: `9071042570516268`
   - Usage: Public property pages, external references

## Field Types

The API supports various field types:

- **text**: Simple text input
- **textarea**: Multi-line text input
- **number**: Numeric input
- **select**: Dropdown selection
- **radio**: Radio button selection
- **checkbox**: Checkbox input
- **date**: Date picker
- **time**: Time picker
- **datetime**: Date and time picker
- **phone**: Phone number input
- **email**: Email input
- **file**: File upload
- **image**: Image upload
- **richtext**: Rich text editor
- **map**: Map location picker
- **switch**: Toggle switch

## Error Responses

All endpoints return consistent error responses:

```json
{
  "error": "Error message description"
}
```

Common HTTP status codes:
- `400`: Bad Request (invalid data)
- `401`: Unauthorized (invalid or missing token)
- `403`: Forbidden (insufficient permissions)
- `404`: Not Found (resource doesn't exist)
- `500`: Internal Server Error


## Best Practices

1. **Always check available fields first**: Use the `/fields` endpoint to get the current field mappings
2. **Handle errors gracefully**: Check for error responses and implement appropriate error handling
3. **Use pagination**: For large datasets, use the pagination parameters
4. **Validate data**: Ensure required fields are provided and data types are correct
   
## Example Usage

### JavaScript/Node.js

```javascript
const API_TOKEN = 'your_api_token_here';
const BASE_URL = 'https://your-domain.com/api/integration';

// Get available fields
async function getFields() {
  const response = await fetch(`${BASE_URL}/fields`, {
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`
    }
  });
  return response.json();
}

// Create a property
async function createProperty(propertyData) {
  const response = await fetch(`${BASE_URL}/properties`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      data: {
        ...propertyData,
        Location: {
          lat: 37.9838,
          lng: 23.7275
        },
        isPublic: true
      }
    })
  });
  return response.json();
}

// Upload images
async function uploadImages(propertyId, files) {
  const formData = new FormData();
  files.forEach(file => {
    formData.append('images', file);
  });

  const response = await fetch(`${BASE_URL}/properties/${propertyId}/images`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`
    },
    body: formData
  });
  return response.json();
}
```

### Python

```python
import requests

API_TOKEN = 'your_api_token_here'
BASE_URL = 'https://your-domain.com/api/integration'

headers = {
    'Authorization': f'Bearer {API_TOKEN}'
}

# Get available fields
def get_fields():
    response = requests.get(f'{BASE_URL}/fields', headers=headers)
    return response.json()

# Create a property
def create_property(property_data):
    response = requests.post(
        f'{BASE_URL}/properties',
        headers={**headers, 'Content-Type': 'application/json'},
        json={
            'data': {
                **property_data,
                'Location': {
                    'lat': 37.9838,
                    'lng': 23.7275
                },
                'isPublic': True
            }
        }
    )
    return response.json()

# Upload images
def upload_images(property_id, image_files):
    files = [('images', file) for file in image_files]
    response = requests.post(
        f'{BASE_URL}/properties/{property_id}/images',
        headers=headers,
        files=files
    )
    return response.json()
```

## cURL Examples

### Create Property with Hierarchical Location
```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "Title": "Beautiful Apartment",
      "Type": "apartment", 
      "Price": 350000,
      "Bedrooms": 3,
      "Bathrooms": 2,
      "Region": {
        "id": 104,
        "name": "Τήνος",
        "nameEN": "Tinos"
      },
      "SubRegion": {
        "id": 2402,
        "name": "Υστέρνια",
        "nameEN": "Ysternia"
      },
      "Area": {
        "id": 123304,
        "name": "Δέση", 
        "nameEN": "Desi"
      },
      "Location": {
        "lat": 37.9838,
        "lng": 23.7275
      },
      "isPublic": true
    }
  }' \
  "https://your-domain.com/api/integration/properties"
```

### Create Property with Simple IDs (Auto-resolve names)
```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "Title": "Modern Villa",
      "Type": "villa",
      "Price": 750000,
      "Bedrooms": 4,
      "Bathrooms": 3,
      "Region": 104,
      "SubRegion": 2402,
      "Area": 123304,
      "Location": {
        "lat": 37.9838,
        "lng": 23.7275
      },
      "isPublic": true
    }
  }' \
  "https://your-domain.com/api/integration/properties"
```

### Update Property with New Location
```bash
curl -X PUT \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "Title": "Updated Property Title",
      "Price": 375000,
      "Region": 105,
      "SubRegion": 2403,
      "Area": 123305,
      "Location": {
        "lat": 38.1234,
        "lng": 23.9876
      },
      "isPublic": false
    }
  }' \
  "https://your-domain.com/api/integration/properties/PROPERTY_ID"
```

##  Summary

### Overview

This external API integration system for Prop360, allowing external applications to perform CRUD operations on properties using API tokens. 

#### 1. Integration API Endpoints

**Properties API:**
- `GET /api/integration/properties` - List properties with pagination
- `POST /api/integration/properties` - Create new property
- `GET /api/integration/properties/{id}` - Get specific property
- `PUT /api/integration/properties/{id}` - Update property
- `DELETE /api/integration/properties/{id}` - Delete property

**Images API:**
- `POST /api/integration/properties/{id}/images` - Upload images to property

**Fields API:**
- `GET /api/integration/fields` - Get available fields for merchant


### Key Features

#### 1. User-Friendly Field Names
- External developers work with human-readable field names
- Automatic mapping between user-friendly names and internal field IDs
- Support for all field types and options

#### 2. Secure Token System
- Cryptographically secure token generation
- Granular permission control
- Usage tracking and monitoring
- Token expiration support

#### 3. Comprehensive CRUD Operations
- Create, read, update, delete properties
- Image upload support
- Pagination for large datasets
- Soft delete implementation


#### 4. Error Handling
- Consistent error responses
- Proper HTTP status codes
- Detailed error messages
- Validation for all inputs


## Support

For API support and questions, please contact the Prop360 development team.