Unit Management
Manage property units in the Sakneen system using the Units API.
Overview
The Units API allows you to create or update property units in the Sakneen system. This is essential for property developers, real estate companies, and property management systems that need to maintain up-to-date unit inventory.
Endpoint
POST /external/apis/v1.0/units
Authentication
All requests require a valid API key in the header:
api-key: YOUR_API_KEY
Request Body Schema
Required Fields
| Field | Type | Description |
|---|---|---|
recordSystemId | string | Unique system identifier for the record |
unitId | string | Unique identifier for the unit |
Optional Fields
| Field | Type | Description | Validation |
|---|---|---|---|
price | number | Base price of the unit | ≥ 0 |
bua | number | Built-up area in square meters | ≥ 0 |
propertyType | string | Type of property | Any string |
status | string | Current status of the unit | Any string |
bedrooms | number | Number of bedrooms | ≥ 0 |
bathrooms | number | Number of bathrooms | ≥ 0 |
landArea | number | Land area in square meters | ≥ 0 |
gardenArea | number | Garden area in square meters | ≥ 0 |
finishingType | string | Type of finishing | Any string |
floor | string | Floor level | Any string |
amenities | string[] | Array of amenity names | Array of strings |
features | string[] | Array of feature names | Array of strings |
saleType | string | Type of sale | primary or resale (default: primary) |
priceByYear | object | Price variations by year | Key-value pairs (year: price) |
priceByPaymentPlan | array | Array of payment plan pricing | See Payment Plan Schema below |
Payment Plan Schema
Each item in priceByPaymentPlan array should contain:
| Field | Type | Required | Description | Validation |
|---|---|---|---|---|
price | number | ✅ Yes | Price for this payment plan | ≥ 0 |
paymentPlanId | string | ✅ Yes | MongoDB ObjectId of payment plan | Valid MongoDB ObjectId |
finishingTypeId | string | ✅ Yes | MongoDB ObjectId of finishing type | Valid MongoDB ObjectId |
numberOfYears | number | ❌ Optional | Payment plan duration in years | ≥ 0 |
Complete Example Request
{
"recordSystemId": "00163EAB688B1EECA9C3E1F963E029CC",
"unitId": "VH-12",
"price": 1200000,
"bua": 120,
"propertyType": "apartment",
"status": "available",
"bedrooms": 2,
"bathrooms": 2,
"landArea": 150,
"gardenArea": 30,
"finishingType": "Fully finished",
"floor": "2nd",
"amenities": ["wifi", "parking", "gym", "pool"],
"features": ["balcony", "parking", "city_view"],
"saleType": "primary",
"priceByYear": {
"2024": 1200000,
"2025": 1250000,
"2026": 1300000
},
"priceByPaymentPlan": [
{
"price": 1200000,
"paymentPlanId": "64a1b2c3d4e5f6789012345",
"finishingTypeId": "64a1b2c3d4e5f6789012346",
"numberOfYears": 5
},
{
"price": 1150000,
"paymentPlanId": "64a1b2c3d4e5f6789012347",
"finishingTypeId": "64a1b2c3d4e5f6789012348",
"numberOfYears": 3
}
]
}
Headers
| Header | Required | Description |
|---|---|---|
api-key | ✅ Yes | Your organization's API key |
Content-Type | ✅ Yes | Must be application/json |
language | ❌ Optional | Language preference (e.g., en-us, ar-eg) |
Response
Success Response (201 Created)
{
"success": true,
"message": "Unit created/updated successfully",
"data": {
"unitId": "VH-12",
"recordSystemId": "00163EAB688B1EECA9C3E1F963E029CC"
}
}
Error Responses
400 Bad Request - Validation Error
{
"statusCode": 400,
"message": [
"recordSystemId should not be empty",
"unitId should not be empty",
"price must be a number conforming to the specified constraints"
],
"error": "Bad Request"
}
401 Unauthorized - Invalid API Key
{
"statusCode": 401,
"message": "Access Denied, API key not provided",
"error": "Unauthorized"
}
Code Examples
cURL
curl -X POST "https://your-domain/external/apis/v1.0/units" \
-H "api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "language: en-us" \
-d '{
"recordSystemId": "00163EAB688B1EECA9C3E1F963E029CC",
"unitId": "VH-12",
"price": 1200000,
"bua": 120,
"propertyType": "apartment",
"status": "available",
"bedrooms": 2,
"bathrooms": 2,
"landArea": 150,
"finishingType": "Fully finished",
"floor": "2nd",
"amenities": ["wifi", "parking", "gym"],
"features": ["balcony", "parking"],
"saleType": "primary"
}'
JavaScript/Node.js
const apiKey = process.env.SAKNEEN_API_KEY;
const baseDomain = process.env.SAKNEEN_DOMAIN;
async function createUnit(unitData) {
try {
const response = await fetch(`https://${baseDomain}/external/apis/v1.0/units`, {
method: 'POST',
headers: {
'api-key': apiKey,
'Content-Type': 'application/json',
'language': 'en-us'
},
body: JSON.stringify(unitData)
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`HTTP ${response.status}: ${errorData.message || response.statusText}`);
}
const result = await response.json();
console.log('Unit created:', result);
return result;
} catch (error) {
console.error('Error creating unit:', error);
throw error;
}
}
// Usage
const unitData = {
recordSystemId: "00163EAB688B1EECA9C3E1F963E029CC",
unitId: "VH-12",
price: 1200000,
bua: 120,
propertyType: "apartment",
status: "available",
bedrooms: 2,
bathrooms: 2,
landArea: 150,
gardenArea: 30,
finishingType: "Fully finished",
floor: "2nd",
amenities: ["wifi", "parking", "gym", "pool"],
features: ["balcony", "parking", "city_view"],
saleType: "primary",
priceByYear: {
"2024": 1200000,
"2025": 1250000
},
priceByPaymentPlan: [
{
price: 1200000,
paymentPlanId: "64a1b2c3d4e5f6789012345",
finishingTypeId: "64a1b2c3d4e5f6789012346",
numberOfYears: 5
}
]
};
createUnit(unitData)
.then(result => console.log('Success:', result))
.catch(error => console.error('Error:', error));
Python
import requests
import os
import json
def create_unit(unit_data):
api_key = os.getenv('SAKNEEN_API_KEY')
base_domain = os.getenv('SAKNEEN_DOMAIN')
url = f'https://{base_domain}/external/apis/v1.0/units'
headers = {
'api-key': api_key,
'Content-Type': 'application/json',
'language': 'en-us'
}
try:
response = requests.post(url, headers=headers, json=unit_data)
response.raise_for_status()
result = response.json()
print(f'Unit created: {result}')
return result
except requests.exceptions.RequestException as e:
print(f'Error creating unit: {e}')
raise
# Usage
unit_data = {
"recordSystemId": "00163EAB688B1EECA9C3E1F963E029CC",
"unitId": "VH-12",
"price": 1200000,
"bua": 120,
"propertyType": "apartment",
"status": "available",
"bedrooms": 2,
"bathrooms": 2,
"landArea": 150,
"gardenArea": 30,
"finishingType": "Fully finished",
"floor": "2nd",
"amenities": ["wifi", "parking", "gym", "pool"],
"features": ["balcony", "parking", "city_view"],
"saleType": "primary",
"priceByYear": {
"2024": 1200000,
"2025": 1250000
},
"priceByPaymentPlan": [
{
"price": 1200000,
"paymentPlanId": "64a1b2c3d4e5f6789012345",
"finishingTypeId": "64a1b2c3d4e5f6789012346",
"numberOfYears": 5
}
]
}
try:
result = create_unit(unit_data)
print(f'Success: {result}')
except Exception as e:
print(f'Error: {e}')
PHP
<?php
function createUnit($unitData) {
$domain = $_ENV['SAKNEEN_DOMAIN']; // your assigned domain
$apiKey = $_ENV['SAKNEEN_API_KEY'];
$headers = [
'api-key: ' . $apiKey,
'Content-Type: application/json'
];
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{$domain}/external/apis/v1.0/units",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($unitData),
CURLOPT_HTTPHEADER => $headers,
]);
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($httpCode !== 201) {
throw new Exception("HTTP Error: $httpCode");
}
return $response;
}
// Usage
$unitData = [
'recordSystemId' => '00163EAB688B1EECA9C3E1F963E029CC',
'unitId' => 'VH-12',
'price' => 12000,
'bua' => 120,
'propertyType' => 'apartment',
'status' => 'available',
'bedrooms' => 2,
'bathrooms' => 2,
'landAres' => 120,
'finishingType' => 'Fully finished',
'deliveryDateType' => 'months',
'deliveryDate' => '01-12-2026',
'deliveryDateMonths' => 25,
'floor' => 'ground',
'amenities' => ['wifi', 'parking'],
'features' => ['parking'],
'saleType' => 'primary'
];
try {
$result = createUnit($unitData);
echo "Unit created: $result\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>
Validation Rules
Required Field Validation
- All required fields must be present and not empty
pricemust be a positive numberpropertyTypemust be one of the allowed valuesstatusmust be one of the allowed values
Data Type Validation
bedroomsandbathroomsmust be integers if providedbuaandlandAresmust be numbers if providedamenitiesandfeaturesmust be arrays if provideddeliveryDatemust follow DD-MM-YYYY format if provided
Business Logic Validation
- If
deliveryDateTypeis "months",deliveryDateMonthsshould be provided - If
deliveryDateTypeis "date",deliveryDateshould be provided unitIdshould be unique within the system
Error Handling
Common Error Scenarios
-
Missing API Key (401)
- Ensure API key is included in headers
- Verify API key is valid
-
Invalid Data (400)
- Check all required fields are present
- Verify data types match the specification
- Ensure enum values are from allowed lists
-
Missing Request Body (403)
- Include request body with unit data
- Ensure Content-Type header is set to application/json
-
Network Issues
- Implement retry logic for transient failures
- Set appropriate timeouts
Best Practices
- Data Validation: Always validate data before sending to API
- Error Handling: Implement comprehensive error handling
- Retry Logic: Add retry mechanisms for network failures
- Logging: Log all API interactions for debugging
- Rate Limiting: Respect API rate limits
- Data Consistency: Ensure unit data is consistent across systems
Use Cases
Property Management Systems
- Sync property units with Sakneen
- Update unit availability and pricing
- Manage unit specifications and features
Real Estate Portals
- Import property inventory
- Update unit status after sales
- Maintain synchronized property data
CRM Integration
- Create units when new developments are added
- Update unit information for sales teams
- Track unit availability for lead management