Properties API Documentation
RESTful API untuk mengelola properti, autentikasi pengguna, dan upload file. Dibangun dengan Express.js, TypeScript, dan Firebase Admin SDK.
Firebase Authentication
Sistem autentikasi berbasis Firebase dengan session cookies yang aman.
File Upload
Upload file dengan integrasi ImageKit untuk optimasi dan CDN.
Firestore Database
Mengelola data properti dengan Firestore untuk skalabilitas tinggi.
Quick Start
Daftar & Login
Buat akun baru atau login untuk mendapatkan session cookie.
Gunakan Session Cookie
Setiap request yang memerlukan autentikasi akan menggunakan session cookie secara otomatis.
Panggil Endpoints
Mulai menggunakan API untuk mengelola properti dan data Anda.
curl --request POST \ --url 'https://your-api-domain.com/auth/login' \ --header 'Content-Type: application/json' \ --data '{ "email": "user@example.com", "password": "password123" }'
Response
{
"ok": true
}
Autentikasi
API ini menggunakan Firebase Authentication dengan session cookies. Setelah login atau signup berhasil, server akan mengatur session cookie secara otomatis. Cookie ini akan digunakan untuk semua request yang memerlukan autentikasi.
Penting
Session cookie akan dikirim secara otomatis oleh browser. Pastikan untuk mengaktifkan credentials (withCredentials) jika menggunakan fetch atau axios.
Rate Limiting
Saat ini tidak ada batasan rate limiting yang diterapkan. Namun, kami menyarankan untuk tidak melakukan lebih dari 100 request per detik per IP.
Health Check
/health
Endpoint untuk memeriksa status API. Tidak memerlukan autentikasi.
Dokumentasi ini dilayani di GET /docs.
curl https://your-api-domain.com/health
Response
{
"ok": true
}
Authentication Endpoints
/auth/login
Login dengan email dan password. Session cookie akan diatur otomatis.
Request Body:
{
"email": "user@example.com",
"password": "password123"
}
curl --request POST \ --url 'https://your-api-domain.com/auth/login' \ --header 'Content-Type: application/json' \ --data '{"email":"user@example.com","password":"password123"}'
Response
{
"ok": true
}
/auth/signup
Mendaftar akun baru. Session cookie akan diatur otomatis.
Request Body:
{
"email": "user@example.com",
"password": "password123",
"displayName": "John Doe" // optional,
"phoneNumber": "+628123456789" // optional
}
/auth/logout
Logout dan hapus session cookie. Memerlukan autentikasi.
Request Body:
{} // empty body
Response
{
"ok": true
}
/auth/me
Mendapatkan informasi user yang sedang login. Memerlukan autentikasi.
curl --request GET \ --url 'https://your-api-domain.com/auth/me'
Response
{
"data": {
"uid": "user123",
"email": "user@example.com",
"displayName": "John Doe",
"role": "user"
}
}
/auth/reset-password
Mengirim email reset password.
Request Body:
{
"email": "user@example.com"
}
Response
{
"ok": true
}
/auth/change-password
Mengubah password. Memerlukan autentikasi.
Request Body:
{
"oldPassword": "oldpassword123",
"newPassword": "newpassword123"
}
Response
{
"ok": true
}
/auth/delete-account
Menghapus akun pengguna (Firestore + Firebase Auth). Memerlukan autentikasi.
Request Body:
{
"password": "password123" // untuk konfirmasi
}
Response
{
"ok": true
}
Accounts Endpoints
/me
Mendapatkan data akun pengguna yang sedang login. Memerlukan autentikasi.
curl --request GET \ --url 'https://your-api-domain.com/me'
Response
{
"data": {
"uid": "user123",
"email": "user@example.com",
"displayName": "John Doe",
"role": "user"
}
}
/me
Memperbarui data akun pengguna. Memerlukan autentikasi.
Request Body:
{
"displayName": "Jane Doe" // optional,
"phoneNumber": "+628123456789" // optional,
"photoURL": "https://example.com/photo.jpg" // optional
}
/accounts
Mendapatkan daftar semua akun. Memerlukan header x-api-secret (bukan session).
Headers:
x-api-secret: your-api-secret
curl --request GET \ --url 'https://your-api-domain.com/accounts' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": [
{ "uid", "email", "displayName", "phoneNumber", "photoURL", "role", "createdAt", "updatedAt" }
]
}
Upload Endpoint
/upload
Upload file ke ImageKit. Maksimal 5MB per file. Memerlukan header x-api-secret.
Headers:
x-api-secret: your-api-secret
Query Parameters (optional):
folder=uploads // default: "uploads"
curl --request POST \ --url 'https://your-api-domain.com/upload?folder=images' \ --header 'x-api-secret: your-api-secret' \ --form 'file=@/path/to/file.jpg'
Response
{
"url": "https://ik.imagekit.io/...",
"path": "images/1234567890-file.jpg",
"contentType": "image/jpeg",
"size": 123456
}
ImageKit Endpoint
/imagekit/auth
Mendapatkan token autentikasi untuk ImageKit client-side upload.
curl --request GET \ --url 'https://your-api-domain.com/imagekit/auth'
Response
{
"token": "abc123...",
"expire": 1623456000,
"signature": "xyz789..."
}
Properties Endpoints
Semua endpoints properties memerlukan autentikasi dan header x-api-secret. Ada CRUD untuk properti utama plus referensi: Type, Location, dan Badge.
Properties (Properti Utama)
/properties/upload/thumbnail
Upload thumbnail gambar ke ImageKit. Multipart file. Maksimal 5MB. Memerlukan header x-api-secret dan autentikasi.
Headers:
x-api-secret: your-api-secret
curl --request POST \ --url 'https://your-api-domain.com/properties/upload/thumbnail' \ --header 'x-api-secret: your-api-secret' \ --form 'file=@/path/to/thumbnail.jpg'
Response
{
"url": "https://ik.imagekit.io/...",
"path": "properties/thumbnails/1234567890-thumbnail.jpg",
"contentType": "image/jpeg",
"size": 123456
}
/properties/upload/image
Upload gambar properti ke ImageKit. Multipart file. Maksimal 5MB. Memerlukan header x-api-secret dan autentikasi.
Headers:
x-api-secret: your-api-secret
curl --request POST \ --url 'https://your-api-domain.com/properties/upload/image' \ --header 'x-api-secret: your-api-secret' \ --form 'file=@/path/to/image.jpg'
Response
{
"url": "https://ik.imagekit.io/...",
"path": "properties/images/1234567890-image.jpg",
"contentType": "image/jpeg",
"size": 123456
}
/properties
Daftar properti (paginated). Memerlukan autentikasi dan header x-api-secret.
Query Parameters (optional):
page=1 // default: 1
curl --request GET \ --url 'https://your-api-domain.com/properties?page=1' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": [
{
"id": "prop001",
"title": "Rumah Minimalis Modern",
"slug": "rumah-minimalis-modern",
"location": {
"name": "Jakarta Selatan",
"locationsId": "loc001"
},
"type": {
"name": "Rumah",
"propertiesTypeId": "type001"
},
"badges": ["New", "Featured"],
"thumbnailUrl": "https://ik.imagekit.io/.../thumbnail1.jpg",
"imageUrl": [
"https://ik.imagekit.io/.../image1.jpg",
"https://ik.imagekit.io/.../image2.jpg"
],
"bedrooms": 3,
"bathrooms": 2,
"area": 150,
"price": "Rp 500.000.000",
"priceValue": 500000000,
"status": "published",
"createdAt": "2026-02-15T10:30:00Z",
"updatedAt": "2026-02-20T14:20:00Z"
},
{
"id": "prop002",
"title": "Apartemen Luxurious",
"slug": "apartemen-luxurious",
"location": {
"name": "Jakarta Pusat",
"locationsId": "loc002"
},
"type": {
"name": "Apartemen",
"propertiesTypeId": "type002"
},
"badges": ["Premium"],
"thumbnailUrl": "https://ik.imagekit.io/.../thumbnail2.jpg",
"imageUrl": [
"https://ik.imagekit.io/.../image3.jpg"
],
"bedrooms": 2,
"bathrooms": 1,
"area": 75,
"price": "Rp 350.000.000",
"priceValue": 350000000,
"status": "published",
"createdAt": "2026-02-10T08:15:00Z",
"updatedAt": "2026-02-18T16:45:00Z"
}
],
"page": 1,
"limit": 10,
"nextPage": 2,
"prevPage": null
}
/properties/search
Cari properti. Memerlukan autentikasi dan header x-api-secret.
Query Parameters:
q=search term // wajib page=1 // optional, default: 1
curl --request GET \ --url 'https://your-api-domain.com/properties/search?q=rumah&page=1' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": [
{
"id": "prop001",
"title": "Rumah Minimalis Modern",
"slug": "rumah-minimalis-modern",
"location": {
"name": "Jakarta Selatan",
"locationsId": "loc001"
},
"type": {
"name": "Rumah",
"propertiesTypeId": "type001"
},
"badges": ["New", "Featured"],
"thumbnailUrl": "https://ik.imagekit.io/.../thumbnail1.jpg",
"imageUrl": [
"https://ik.imagekit.io/.../image1.jpg"
],
"bedrooms": 3,
"bathrooms": 2,
"area": 150,
"price": "Rp 500.000.000",
"priceValue": 500000000,
"status": "published"
}
],
"page": 1,
"limit": 10
}
/properties/:id
Detail satu properti berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.
curl --request GET \ --url 'https://your-api-domain.com/properties/prop001' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": {
"id": "prop001",
"title": "Rumah Minimalis Modern",
"slug": "rumah-minimalis-modern",
"content": "Rumah minimalis modern dengan desain yang elegan dan nyaman. Terletak di lokasi strategis dengan akses mudah ke berbagai fasilitas umum.",
"location": {
"name": "Jakarta Selatan",
"locationsId": "loc001"
},
"type": {
"name": "Rumah",
"propertiesTypeId": "type001"
},
"badges": [
"New",
"Featured"
],
"thumbnailUrl": "https://ik.imagekit.io/.../thumbnail1.jpg",
"imageUrl": [
"https://ik.imagekit.io/.../image1.jpg",
"https://ik.imagekit.io/.../image2.jpg",
"https://ik.imagekit.io/.../image3.jpg"
],
"bedrooms": 3,
"bathrooms": 2,
"area": 150,
"price": "Rp 500.000.000",
"priceValue": 500000000,
"propertiesTypeId": "type001",
"status": "published",
"createdAt": "2026-02-15T10:30:00Z",
"updatedAt": "2026-02-20T14:20:00Z"
}
}
/properties
Buat properti baru. Memerlukan autentikasi dan header x-api-secret.
Request Body:
{
"title": "Rumah Minimalis",
"slug": "rumah-minimalis" // optional,
"location": {
"name": "Jakarta",
"locationsId": "location123"
},
"type": {
"name": "Rumah",
"propertiesTypeId": "type123"
},
"badges": ["badge1", "badge2"] // optional,
"content": "Deskripsi properti...",
"thumbnailUrl": "https://ik.imagekit.io/.../thumbnail.jpg",
"imageUrl": ["https://ik.imagekit.io/.../image1.jpg"] // optional,
"bedrooms": 3,
"bathrooms": 2,
"area": 150,
"price": "Rp 500.000.000",
"priceValue": 500000000,
"propertiesTypeId": "type123" // optional,
"status": "published" // optional: draft|published|archived
}
Response
{
"data": {
"id": "property123",
"title": "Rumah Minimalis",
...
}
}
/properties/:id
Update properti. Semua field optional. Memerlukan autentikasi dan header x-api-secret.
Request Body (semua field optional):
{
"title": "Rumah Minimalis Updated" // optional,
"location": { ... } // optional,
"type": { ... } // optional,
"badges": [ ... ] // optional,
"content": "..." // optional,
"thumbnailUrl": "..." // optional,
"imageUrl": [ ... ] // optional,
"bedrooms": 4 // optional,
"bathrooms": 3 // optional,
"area": 200 // optional,
"price": "Rp 600.000.000" // optional,
"priceValue": 600000000 // optional,
"status": "published" // optional
}
Response
{
"data": {
"id": "property123",
...
}
}
/properties/:id
Hapus properti. Memerlukan autentikasi dan header x-api-secret.
Response
{
"ok": true
}
Properties Type
/properties-type
Mendapatkan semua property types. Memerlukan autentikasi dan header x-api-secret.
curl --request GET \ --url 'https://your-api-domain.com/properties-type' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": [
{
"id": "type001",
"name": "Rumah",
"isActive": true,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-02-10T14:30:00Z"
},
{
"id": "type002",
"name": "Apartemen",
"isActive": true,
"createdAt": "2026-01-20T09:15:00Z",
"updatedAt": "2026-02-12T11:20:00Z"
}
]
}
/properties-type/:id
Mendapatkan property type berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.
curl --request GET \ --url 'https://your-api-domain.com/properties-type/type001' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": {
"id": "type001",
"name": "Rumah",
"isActive": true,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-02-10T14:30:00Z"
}
}
/properties-type
Membuat property type baru. Memerlukan autentikasi dan header x-api-secret.
Request Body:
{
"name": "Rumah",
"isActive": true
}
Response
{
"data": {
"id": "type001",
"name": "Rumah",
"isActive": true,
"createdAt": "2026-02-21T10:00:00Z",
"updatedAt": "2026-02-21T10:00:00Z"
}
}
/properties-type/:id
Memperbarui property type. Semua field optional. Memerlukan autentikasi dan header x-api-secret.
Request Body (semua field optional):
{
"name": "Rumah Updated" // optional,
"isActive": false // optional
}
Response
{
"data": {
"id": "type001",
"name": "Rumah Updated",
"isActive": false,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-02-21T15:30:00Z"
}
}
/properties-type/:id
Menghapus property type. Memerlukan autentikasi dan header x-api-secret.
Response
{
"ok": true
}
Properties Location
/properties-location
Mendapatkan semua property locations. Memerlukan autentikasi dan header x-api-secret.
curl --request GET \ --url 'https://your-api-domain.com/properties-location' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": [
{
"id": "loc001",
"name": "Jakarta Selatan",
"isActive": true,
"createdAt": "2026-01-10T08:00:00Z",
"updatedAt": "2026-02-05T12:15:00Z"
},
{
"id": "loc002",
"name": "Jakarta Pusat",
"isActive": true,
"createdAt": "2026-01-12T09:30:00Z",
"updatedAt": "2026-02-08T10:45:00Z"
}
]
}
/properties-location/:id
Mendapatkan property location berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.
curl --request GET \ --url 'https://your-api-domain.com/properties-location/loc001' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": {
"id": "loc001",
"name": "Jakarta Selatan",
"isActive": true,
"createdAt": "2026-01-10T08:00:00Z",
"updatedAt": "2026-02-05T12:15:00Z"
}
}
/properties-location
Membuat property location baru. Memerlukan autentikasi dan header x-api-secret.
Request Body:
{
"name": "Jakarta Selatan",
"isActive": true
}
Response
{
"data": {
"id": "loc001",
"name": "Jakarta Selatan",
"isActive": true,
"createdAt": "2026-02-21T10:00:00Z",
"updatedAt": "2026-02-21T10:00:00Z"
}
}
/properties-location/:id
Memperbarui property location. Semua field optional. Memerlukan autentikasi dan header x-api-secret.
Request Body (semua field optional):
{
"name": "Jakarta Selatan Updated" // optional,
"isActive": false // optional
}
Response
{
"data": {
"id": "loc001",
"name": "Jakarta Selatan Updated",
"isActive": false,
"createdAt": "2026-01-10T08:00:00Z",
"updatedAt": "2026-02-21T15:30:00Z"
}
}
/properties-location/:id
Menghapus property location. Memerlukan autentikasi dan header x-api-secret.
Response
{
"ok": true
}
Properties Badge
/properties-badge
Mendapatkan semua property badges. Memerlukan autentikasi dan header x-api-secret.
curl --request GET \ --url 'https://your-api-domain.com/properties-badge' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": [
{
"id": "badge001",
"name": "New",
"color": "#10b981",
"isActive": true,
"createdAt": "2026-01-05T07:00:00Z",
"updatedAt": "2026-02-01T09:20:00Z"
},
{
"id": "badge002",
"name": "Featured",
"color": "#f59e0b",
"isActive": true,
"createdAt": "2026-01-08T08:30:00Z",
"updatedAt": "2026-02-03T11:10:00Z"
}
]
}
/properties-badge/:id
Mendapatkan property badge berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.
curl --request GET \ --url 'https://your-api-domain.com/properties-badge/badge001' \ --header 'x-api-secret: your-api-secret'
Response
{
"data": {
"id": "badge001",
"name": "New",
"color": "#10b981",
"isActive": true,
"createdAt": "2026-01-05T07:00:00Z",
"updatedAt": "2026-02-01T09:20:00Z"
}
}
/properties-badge
Membuat property badge baru. Memerlukan autentikasi dan header x-api-secret.
Request Body:
{
"name": "New",
"color": "#10b981" // optional,
"isActive": true
}
Response
{
"data": {
"id": "badge001",
"name": "New",
"color": "#10b981",
"isActive": true,
"createdAt": "2026-02-21T10:00:00Z",
"updatedAt": "2026-02-21T10:00:00Z"
}
}
/properties-badge/:id
Memperbarui property badge. Semua field optional. Memerlukan autentikasi dan header x-api-secret.
Request Body (semua field optional):
{
"name": "New Updated" // optional,
"color": "#3b82f6" // optional,
"isActive": false // optional
}
Response
{
"data": {
"id": "badge001",
"name": "New Updated",
"color": "#3b82f6",
"isActive": false,
"createdAt": "2026-01-05T07:00:00Z",
"updatedAt": "2026-02-21T15:30:00Z"
}
}
/properties-badge/:id
Menghapus property badge. Memerlukan autentikasi dan header x-api-secret.
Response
{
"ok": true
}