http://localhost:8080
All endpoints require Bearer token authentication unless marked as public.
Authorization: Bearer <your_jwt_token>
Endpoint: GET /api/payments
Roles: ADMIN, ACCOUNTANT
GET /api/payments
Authorization: Bearer <accountant_token>GET /api/payments?page=0&size=10&sortBy=dueDate&sortDirection=ASC&statuses=PENDING,SYSTEM_PENDING&overdue=true
Authorization: Bearer <accountant_token>GET /api/payments?paymentTypes=SALARY,BONUS&statuses=SYSTEM_PENDING
Authorization: Bearer <accountant_token>GET /api/payments?contractId=<uuid>
Authorization: Bearer <accountant_token>GET /api/payments?dueDateFrom=2024-01-01&dueDateTo=2024-12-31
Authorization: Bearer <accountant_token>Expected Response:
{
"statusCode": 200,
"message": "Payments retrieved successfully",
"data": [
{
"id": "uuid",
"paymentType": "SALARY",
"status": "SYSTEM_PENDING",
"amount": 15000000,
"dueDate": "2024-12-01",
"paidDate": null,
"payerId": null,
"payerName": "Company",
"payerRole": "COMPANY",
"payeeId": "uuid",
"payeeName": "Nguyen Van A",
"payeeRole": "SALESAGENT",
"contractId": null,
"propertyId": null,
"createdAt": "2024-11-25T10:00:00"
}
],
"paging": {
"page": 0,
"size": 20,
"totalElements": 100,
"totalPages": 5
}
}Endpoint: GET /api/payments/{paymentId}
Roles: ADMIN, ACCOUNTANT
GET /api/payments/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer <accountant_token>Expected Response:
{
"statusCode": 200,
"message": "Payment retrieved successfully",
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"paymentType": "INSTALLMENT",
"status": "PENDING",
"amount": 50000000,
"penaltyAmount": 0,
"dueDate": "2024-12-15",
"paidDate": null,
"installmentNumber": 3,
"overdueDays": 0,
"penaltyApplied": false,
"payerId": "uuid",
"payerFirstName": "Tran",
"payerLastName": "Van B",
"payerRole": "CUSTOMER",
"payerPhone": "0901234567",
"contractId": "uuid",
"contractNumber": "PUR-12345-00001",
"contractType": "PURCHASE",
"contractStatus": "ACTIVE",
"propertyId": "uuid",
"propertyTitle": "Căn hộ cao cấp Quận 1",
"propertyAddress": "123 Nguyen Hue, Q1, HCM"
}
}Endpoint: PATCH /api/payments/{paymentId}/status
Roles: ADMIN, ACCOUNTANT
PATCH /api/payments/123e4567-e89b-12d3-a456-426614174000/status
Authorization: Bearer <accountant_token>
Content-Type: application/json
{
"status": "SUCCESS",
"notes": "Đã nhận tiền mặt từ khách hàng",
"transactionReference": "TXN-2024-001234"
}PATCH /api/payments/<salary_payment_id>/status
Authorization: Bearer <accountant_token>
Content-Type: application/json
{
"status": "SYSTEM_SUCCESS",
"notes": "Đã chuyển khoản lương tháng 11",
"transactionReference": "BANK-TXN-20241130-001"
}Expected Response:
{
"statusCode": 200,
"message": "Payment status updated successfully",
"data": {
"id": "uuid",
"status": "SUCCESS",
"paidDate": "2024-12-01",
"notes": "Đã nhận tiền mặt từ khách hàng",
"transactionReference": "TXN-2024-001234"
}
}Endpoint: POST /api/payments/salary
Roles: ADMIN, ACCOUNTANT
POST /api/payments/salary
Authorization: Bearer <accountant_token>
Content-Type: application/json
{
"agentId": "123e4567-e89b-12d3-a456-426614174000",
"amount": 15000000,
"dueDate": "2024-12-01",
"notes": "Lương tháng 12/2024"
}Expected Response:
{
"statusCode": 200,
"message": "Salary payment created successfully",
"data": {
"id": "uuid",
"paymentType": "SALARY",
"status": "SYSTEM_PENDING",
"amount": 15000000,
"dueDate": "2024-12-01",
"payerId": null,
"payerFirstName": "Company",
"payerRole": "COMPANY",
"payeeId": "uuid",
"payeeFirstName": "Nguyen",
"payeeLastName": "Van A",
"payeeRole": "SALESAGENT",
"agentId": "uuid",
"agentEmployeeCode": "AGT-001"
}
}Endpoint: POST /api/payments/bonus
Roles: ADMIN, ACCOUNTANT
POST /api/payments/bonus
Authorization: Bearer <accountant_token>
Content-Type: application/json
{
"agentId": "123e4567-e89b-12d3-a456-426614174000",
"amount": 5000000,
"notes": "Thưởng KPI tháng 11 - Hoàn thành 150% chỉ tiêu"
}Workflow: When a customer completes a contract payment via PayOS (deposit, installment, full payment, monthly rent, sale, or rental), the PayOS webhook handler automatically creates an owner payout record with paymentMethod = OWNER_PAYOUT and status = SYSTEM_PENDING. This represents the net amount the company owes the property owner after deducting commission (service fees are already settled before a listing goes live).
Auto-Creation Logic:
- Customer pays via PayOS (e.g., 100,000,000 VND deposit)
- Webhook handler validates payment SUCCESS
- System calculates:
- Commission: customerAmount × property.commissionRate (e.g., 5%)
- Net to owner: customerAmount - commission
- Creates Payment record with
paymentType = <original type>,paymentMethod = OWNER_PAYOUT,amount = net,status = SYSTEM_PENDING
Example Calculation:
Customer pays: 100,000,000 VND (DEPOSIT)
Commission (5%): 5,000,000 VND
---
Owner payout: 95,000,000 VND
Endpoint: PATCH /api/payments/{paymentId}/status (use the ID of the auto-created owner payout record)
Roles: ADMIN, ACCOUNTANT
PATCH /api/payments/<owner_payout_payment_id>/status
Authorization: Bearer <accountant_token>
Content-Type: application/json
{
"status": "SYSTEM_SUCCESS",
"notes": "Forwarded net amount to property owner via bank transfer",
"transactionReference": "BANK-REF-20241201-002"
}Expected Result: Payment status changes to SYSTEM_SUCCESS, paidDate is auto-populated. The owner receives the net amount after commission/service fee deduction.
Workflow: When a property owner settles a cancellation refund via PayOS (POST /api/payments/contracts/{contractId}/cancellation-refund), the system automatically creates a new payment record with paymentMethod = COMPANY_PAYOUT so accountants can mark when the company forwards the money back to the customer (penalty already deducted).
Endpoint: PATCH /api/payments/{paymentId}/status (use the ID of the auto-created payout record)
Roles: ADMIN, ACCOUNTANT
PATCH /api/payments/<refund_payout_payment_id>/status
Authorization: Bearer <accountant_token>
Content-Type: application/json
{
"status": "SYSTEM_SUCCESS",
"notes": "Refund forwarded to customer via bank transfer",
"transactionReference": "BANK-REF-20241201-001"
}Expected Result: Payment status flips to SYSTEM_SUCCESS, paidDate is auto-populated, and the refund workflow now reflects both owner settlement (PayOS) and company payout (manual).
Endpoint: POST /appointment
Roles: CUSTOMER, ADMIN, SALESAGENT
Description: Creates a viewing appointment. Customers create for themselves, while Admin/Agent can create on behalf of customers and optionally assign an agent immediately.
POST /appointment
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"propertyId": "123e4567-e89b-12d3-a456-426614174000",
"requestedDate": "2024-12-15T10:00:00",
"customerRequirements": "Cần xem vào buổi sáng, có thể đi xe lăn"
}Expected Response:
{
"statusCode": 200,
"message": "Appointment created successfully",
"data": {
"appointmentId": "uuid",
"propertyId": "uuid",
"propertyTitle": "Căn hộ cao cấp Quận 7",
"propertyAddress": "123 Nguyễn Văn Linh, Q7, HCM",
"requestedDate": "2024-12-15T10:00:00",
"status": "PENDING",
"customerRequirements": "Cần xem vào buổi sáng, có thể đi xe lăn",
"agentId": null,
"agentName": null,
"createdAt": "2024-12-01T14:30:00",
"message": "Your viewing appointment has been booked. You will be notified when an agent confirms the appointment."
}
}POST /appointment
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"propertyId": "123e4567-e89b-12d3-a456-426614174000",
"customerId": "customer-uuid-here",
"requestedDate": "2024-12-20T14:00:00",
"customerRequirements": "Customer prefers afternoon viewing"
}Expected Response:
{
"statusCode": 200,
"message": "Appointment created successfully",
"data": {
"appointmentId": "uuid",
"status": "PENDING",
"message": "Your viewing appointment has been booked. You will be notified when an agent confirms the appointment."
}
}POST /appointment
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"propertyId": "123e4567-e89b-12d3-a456-426614174000",
"customerId": "customer-uuid-here",
"agentId": "agent-uuid-here",
"requestedDate": "2024-12-18T10:00:00",
"customerRequirements": "VIP customer, needs premium service"
}Expected Response:
{
"statusCode": 200,
"message": "Appointment created successfully",
"data": {
"appointmentId": "uuid",
"status": "CONFIRMED",
"agentId": "agent-uuid-here",
"agentName": "Nguyen Van A",
"message": "Appointment created and assigned to agent Nguyen Van A"
}
}Note: When an agent is assigned during creation, the status is automatically set to CONFIRMED instead of PENDING.
POST /appointment
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"propertyId": "123e4567-e89b-12d3-a456-426614174000",
"requestedDate": "2024-12-20T14:00:00"
}POST /appointment
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"propertyId": "<sold_property_id>",
"requestedDate": "2024-12-15T10:00:00"
}Expected Error Response:
{
"statusCode": 400,
"message": "Property is not available for viewing"
}POST /appointment
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"propertyId": "<property_with_existing_appointment>",
"requestedDate": "2024-12-16T10:00:00"
}Expected Error Response:
{
"statusCode": 400,
"message": "You already have a pending or confirmed appointment for this property"
}Endpoint: PATCH /appointment/{appointmentId}/cancel
Roles: CUSTOMER, SALESAGENT, ADMIN
Description: Changes the appointment status to CANCELLED instead of deleting it. This maintains audit trail and prevents data loss.
PATCH /appointment/123e4567-e89b-12d3-a456-426614174000/cancel
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"reason": "Đổi lịch công tác"
}PATCH /appointment/123e4567-e89b-12d3-a456-426614174000/cancel
Authorization: Bearer <agent_token>
Content-Type: application/json
{
"reason": "Khách hàng không liên lạc được"
}PATCH /appointment/123e4567-e89b-12d3-a456-426614174000/cancel
Authorization: Bearer <customer_token>
Content-Type: application/json
{}Expected Response:
{
"statusCode": 200,
"message": "Appointment cancelled successfully",
"data": true
}Note: The appointment is soft-deleted by changing its status to CANCELLED. The record remains in the database for auditing purposes.
Endpoint: GET /appointment/viewing-cards
Roles: CUSTOMER
GET /appointment/viewing-cards?page=1&limit=10
Authorization: Bearer <customer_token>GET /appointment/viewing-cards?statusEnum=PENDING&page=1&limit=10
Authorization: Bearer <customer_token>GET /appointment/viewing-cards?day=15&month=12&year=2024
Authorization: Bearer <customer_token>Endpoint: GET /appointment/viewing-details/{id}
Roles: CUSTOMER
GET /appointment/viewing-details/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer <customer_token>Endpoint: PATCH /appointment/{appointmentId}/rate
Roles: CUSTOMER
PATCH /appointment/123e4567-e89b-12d3-a456-426614174000/rate
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"rating": 5,
"comment": "Excellent service, agent was very professional and knowledgeable"
}PATCH /appointment/123e4567-e89b-12d3-a456-426614174000/rate
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"rating": 4
}Expected Response:
{
"statusCode": 200,
"message": "Appointment rated successfully",
"data": true
}Endpoint: GET /appointment/admin/viewing-list
Roles: ADMIN, SALESAGENT
GET /appointment/admin/viewing-list?page=1&limit=20&sortType=desc
Authorization: Bearer <admin_token>GET /appointment/admin/viewing-list?statusEnums=PENDING,CONFIRMED&requestDateFrom=2024-12-01T00:00:00&requestDateTo=2024-12-31T23:59:59
Authorization: Bearer <admin_token>GET /appointment/admin/viewing-list?propertyName=căn hộ&customerName=nguyen&page=1&limit=10
Authorization: Bearer <admin_token>Endpoint: GET /appointment/admin-agent/viewing-details/{id}
Roles: ADMIN, SALESAGENT
GET /appointment/admin-agent/viewing-details/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer <admin_token>Endpoint: POST /contracts
Roles: ADMIN, SALESAGENT
POST /contracts
Authorization: Bearer <agent_token>
Content-Type: application/json
{
"propertyId": "123e4567-e89b-12d3-a456-426614174000",
"customerId": "223e4567-e89b-12d3-a456-426614174001",
"agentId": "323e4567-e89b-12d3-a456-426614174002",
"contractType": "PURCHASE",
"startDate": "2024-12-01",
"endDate": "2026-12-01",
"specialTerms": "Thanh toán theo tiến độ xây dựng",
"contractPaymentType": "MORTGAGE",
"totalContractAmount": 5000000000,
"depositAmount": 500000000,
"advancePaymentAmount": 1000000000,
"installmentAmount": 24,
"progressMilestone": 0.3,
"latePaymentPenaltyRate": 0.05,
"specialConditions": "Bàn giao nhà Q4/2025"
}POST /contracts
Authorization: Bearer <agent_token>
Content-Type: application/json
{
"propertyId": "123e4567-e89b-12d3-a456-426614174000",
"customerId": "223e4567-e89b-12d3-a456-426614174001",
"agentId": "323e4567-e89b-12d3-a456-426614174002",
"contractType": "RENTAL",
"startDate": "2024-12-01",
"endDate": "2025-12-01",
"specialTerms": "Thanh toán vào ngày 5 hàng tháng",
"contractPaymentType": "MONTHLY_RENT",
"totalContractAmount": 180000000,
"depositAmount": 30000000,
"latePaymentPenaltyRate": 0.02,
"specialConditions": "Không được nuôi thú cưng"
}Endpoint: GET /contracts/{contractId}
Roles: ADMIN, SALESAGENT, CUSTOMER
GET /contracts/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer <token>Endpoint: GET /contracts
Roles: ADMIN, SALESAGENT
GET /contracts?page=0&size=20
Authorization: Bearer <admin_token>GET /contracts?contractTypes=PURCHASE,RENTAL&statuses=ACTIVE
Authorization: Bearer <admin_token>GET /contracts?agentId=<agent_uuid>
Authorization: Bearer <admin_token>GET /contracts?search=PUR-173
Authorization: Bearer <admin_token>GET /contracts?startDateFrom=2024-01-01&startDateTo=2024-12-31
Authorization: Bearer <admin_token>Endpoint: PUT /contracts/{contractId}
Roles: ADMIN, SALESAGENT
PUT /contracts/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer <agent_token>
Content-Type: application/json
{
"endDate": "2027-01-01",
"specialTerms": "Điều khoản mới: Gia hạn thêm 1 tháng",
"latePaymentPenaltyRate": 0.06,
"specialConditions": "Cập nhật điều kiện thanh toán"
}PUT /contracts/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer <agent_token>
Content-Type: application/json
{
"status": "PENDING_SIGNING"
}Endpoint: POST /contracts/{contractId}/sign
Roles: ADMIN, SALESAGENT
POST /contracts/123e4567-e89b-12d3-a456-426614174000/sign
Authorization: Bearer <agent_token>Expected Response:
{
"statusCode": 200,
"message": "Contract signed successfully",
"data": {
"id": "uuid",
"contractNumber": "PUR-17329845-00001",
"status": "ACTIVE",
"signedAt": "2024-12-01T15:30:00"
}
}Endpoint: POST /contracts/{contractId}/complete
Roles: ADMIN, SALESAGENT
POST /contracts/123e4567-e89b-12d3-a456-426614174000/complete
Authorization: Bearer <agent_token>POST /contracts/<contract_with_unpaid>/complete
Authorization: Bearer <agent_token>Expected Error Response:
{
"statusCode": 400,
"message": "Cannot complete contract with unpaid payments"
}Endpoint: POST /contracts/{contractId}/cancel
Roles: ADMIN, SALESAGENT, CUSTOMER
POST /contracts/123e4567-e89b-12d3-a456-426614174000/cancel
Authorization: Bearer <customer_token>
Content-Type: application/json
{
"reason": "Thay đổi kế hoạch tài chính"
}POST /contracts/123e4567-e89b-12d3-a456-426614174000/cancel
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"reason": "Hủy theo yêu cầu của chủ đầu tư",
"waivePenalty": true
}Expected Response:
{
"statusCode": 200,
"message": "Contract cancelled successfully",
"data": {
"id": "uuid",
"status": "CANCELLED",
"cancellationReason": "Thay đổi kế hoạch tài chính",
"cancellationPenalty": 850000000,
"cancelledBy": "CUSTOMER"
}
}Endpoint: GET /contracts/{contractId}/penalty
Roles: ADMIN, SALESAGENT, CUSTOMER
GET /contracts/123e4567-e89b-12d3-a456-426614174000/penalty
Authorization: Bearer <customer_token>Expected Response:
{
"statusCode": 200,
"message": "Cancellation penalty calculated",
"data": 850000000
}Endpoint: GET /contracts/my
Roles: CUSTOMER
GET /contracts/my?page=0&size=10
Authorization: Bearer <customer_token>GET /contracts/my?statuses=ACTIVE,COMPLETED
Authorization: Bearer <customer_token>Endpoint: GET /contracts/agent/my
Roles: SALESAGENT
GET /contracts/agent/my?page=0&size=10
Authorization: Bearer <agent_token>GET /contracts/agent/my?statuses=PENDING_SIGNING,ACTIVE
Authorization: Bearer <agent_token>Endpoint: POST /contracts/{contractId}/rate
Roles: CUSTOMER
POST /contracts/123e4567-e89b-12d3-a456-426614174000/rate?rating=5&comment=Dịch vụ rất tốt, nhân viên nhiệt tình
Authorization: Bearer <customer_token>POST /contracts/123e4567-e89b-12d3-a456-426614174000/rate?rating=4
Authorization: Bearer <customer_token>POST /contracts/<active_contract_id>/rate?rating=5
Authorization: Bearer <customer_token>Expected Error Response:
{
"statusCode": 400,
"message": "Can only rate completed contracts"
}{
"statusCode": 400,
"message": "Validation error message"
}{
"statusCode": 401,
"message": "Unauthorized"
}{
"statusCode": 403,
"message": "Access denied"
}{
"statusCode": 404,
"message": "Resource not found: <id>"
}| Role | Username | Description |
|---|---|---|
| ADMIN | admin@test.com | Full access |
| ACCOUNTANT | accountant@test.com | Payment management |
| SALESAGENT | agent@test.com | Contract & appointment handling |
| CUSTOMER | customer@test.com | Booking & viewing |
| PROPERTY_OWNER | owner@test.com | Property listings |
- Property - At least one active property for booking
- SaleAgent - For salary/bonus payments
- Customer - For booking appointments
- Contract - In various statuses (DRAFT, ACTIVE, COMPLETED)
- Payment - Various types and statuses
📁 BatDongScam API Tests
├── 📁 Auth
│ ├── Login as Admin
│ ├── Login as Accountant
│ ├── Login as Agent
│ ├── Login as Customer
│ └── Login as Owner
│
├── 📁 Payment
│ ├── Get All Payments
│ ├── Get Payment by ID
│ ├── Update Payment Status
│ ├── Create Salary Payment
│ └── Create Bonus Payment
│
├── 📁 Appointment
│ ├── Create Appointment
│ ├── Cancel Appointment
│ ├── Get My Viewing Cards
│ ├── Get Viewing Details
│ ├── Rate Appointment
│ ├── [Admin] Get Viewing List
│ └── [Admin/Agent] Get Viewing Details
│
├── 📁 Contract
│ ├── Create Contract (Purchase)
│ ├── Create Contract (Rental)
│ ├── Get Contract by ID
│ ├── List Contracts
│ ├── Update Contract
│ ├── Sign Contract
│ ├── Cancel Contract
│ ├── Get My Contracts
│ ├── Get Agent Contracts
│ └── Rate Contract
│
├── 📁 Payment Flow (PayOS)
│ ├── Create Contract Payment Link
│ ├── Create Owner Refund Link
│ ├── Webhook Handler
│ └── Get Payment Link Status
│
└── 📁 Public
├── Get Public Properties
├── Get Property Details
└── Search Properties