# 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.