API v1.0

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

1

Daftar & Login

Buat akun baru atau login untuk mendapatkan session cookie.

2

Gunakan Session Cookie

Setiap request yang memerlukan autentikasi akan menggunakan session cookie secara otomatis.

3

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

GET /health

Endpoint untuk memeriksa status API. Tidak memerlukan autentikasi.

Dokumentasi ini dilayani di GET /docs.

cURL
curl https://your-api-domain.com/health
                                

Response

{
  "ok": true
}
                            

Authentication Endpoints

POST /auth/login

Login dengan email dan password. Session cookie akan diatur otomatis.

Request Body:

{
  "email": "user@example.com",
  "password": "password123"
}
                                
cURL
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
}
                            
POST /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
}
                                
POST /auth/logout

Logout dan hapus session cookie. Memerlukan autentikasi.

Request Body:

{} // empty body
                                

Response

{
  "ok": true
}
                            
GET /auth/me

Mendapatkan informasi user yang sedang login. Memerlukan autentikasi.

cURL
curl --request GET \
  --url 'https://your-api-domain.com/auth/me'
                                

Response

{
  "data": {
    "uid": "user123",
    "email": "user@example.com",
    "displayName": "John Doe",
    "role": "user"
  }
}
                            
POST /auth/reset-password

Mengirim email reset password.

Request Body:

{
  "email": "user@example.com"
}
                                

Response

{
  "ok": true
}
                            
POST /auth/change-password

Mengubah password. Memerlukan autentikasi.

Request Body:

{
  "oldPassword": "oldpassword123",
  "newPassword": "newpassword123"
}
                                

Response

{
  "ok": true
}
                            
DELETE /auth/delete-account

Menghapus akun pengguna (Firestore + Firebase Auth). Memerlukan autentikasi.

Request Body:

{
  "password": "password123" // untuk konfirmasi
}
                                

Response

{
  "ok": true
}
                            

Accounts Endpoints

GET /me

Mendapatkan data akun pengguna yang sedang login. Memerlukan autentikasi.

cURL
curl --request GET \
  --url 'https://your-api-domain.com/me'
                                

Response

{
  "data": {
    "uid": "user123",
    "email": "user@example.com",
    "displayName": "John Doe",
    "role": "user"
  }
}
                            
PATCH /me

Memperbarui data akun pengguna. Memerlukan autentikasi.

Request Body:

{
  "displayName": "Jane Doe" // optional,
  "phoneNumber": "+628123456789" // optional,
  "photoURL": "https://example.com/photo.jpg" // optional
}
                                
GET /accounts

Mendapatkan daftar semua akun. Memerlukan header x-api-secret (bukan session).

Headers:

x-api-secret: your-api-secret
cURL
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

POST /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
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

GET /imagekit/auth

Mendapatkan token autentikasi untuk ImageKit client-side upload.

cURL
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)

POST /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
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
}
                                    
POST /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
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
}
                                    
GET /properties

Daftar properti (paginated). Memerlukan autentikasi dan header x-api-secret.

Query Parameters (optional):

page=1 // default: 1
                                        
cURL
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
}
                                    
GET /properties/search

Cari properti. Memerlukan autentikasi dan header x-api-secret.

Query Parameters:

q=search term // wajib
page=1 // optional, default: 1
                                        
cURL
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
}
                                    
GET /properties/:id

Detail satu properti berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.

cURL
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"
  }
}
                                    
POST /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",
    ...
  }
}
                                    
PATCH /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",
    ...
  }
}
                                    
DELETE /properties/:id

Hapus properti. Memerlukan autentikasi dan header x-api-secret.

Response

{
  "ok": true
}
                                    

Properties Type

GET /properties-type

Mendapatkan semua property types. Memerlukan autentikasi dan header x-api-secret.

cURL
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"
    }
  ]
}
                                    
GET /properties-type/:id

Mendapatkan property type berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.

cURL
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"
  }
}
                                    
POST /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"
  }
}
                                    
PATCH /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"
  }
}
                                    
DELETE /properties-type/:id

Menghapus property type. Memerlukan autentikasi dan header x-api-secret.

Response

{
  "ok": true
}
                                    

Properties Location

GET /properties-location

Mendapatkan semua property locations. Memerlukan autentikasi dan header x-api-secret.

cURL
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"
    }
  ]
}
                                    
GET /properties-location/:id

Mendapatkan property location berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.

cURL
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"
  }
}
                                    
POST /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"
  }
}
                                    
PATCH /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"
  }
}
                                    
DELETE /properties-location/:id

Menghapus property location. Memerlukan autentikasi dan header x-api-secret.

Response

{
  "ok": true
}
                                    

Properties Badge

GET /properties-badge

Mendapatkan semua property badges. Memerlukan autentikasi dan header x-api-secret.

cURL
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"
    }
  ]
}
                                    
GET /properties-badge/:id

Mendapatkan property badge berdasarkan ID. Memerlukan autentikasi dan header x-api-secret.

cURL
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"
  }
}
                                    
POST /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"
  }
}
                                    
PATCH /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"
  }
}
                                    
DELETE /properties-badge/:id

Menghapus property badge. Memerlukan autentikasi dan header x-api-secret.

Response

{
  "ok": true
}