Download OpenAPI specification:
This is the API documentation for Novowatt app.
Verify OTP for the authenticated user's current email,
then set email_verified=true for that user.
This endpoint requires Authorization token.
| otp required | string OTP code sent from |
{- "otp": "123456"
}{- "ok": true,
- "msg": "Email verified successfully"
}Send OTP code via SMS for phone-based authentication (login or registration).
| phone required | string Singapore phone number. Accepts either 8 digits (old app) or full 65XXXXXXXX format. |
{- "ok": true,
- "msg": "OTP sent"
}Verify OTP for phone login.
is_new_account to determine whether to show onboarding screens.| phone required | string Singapore phone number. Accepts either 8 digits (old app) or full 65XXXXXXXX format. |
| otp required | string OTP code sent by /send/otp. |
| fcm_token | string Optional device push token. |
{- "phone": "91234567",
- "otp": "123456",
- "fcm_token": "fcm_device_token"
}{- "ok": true,
- "msg": "OTP verified and login success",
- "data": {
- "phone": "6591234567",
- "has_account": true,
- "is_new_account": false,
- "user": {
- "_id": "67f1234567890abcde123456",
- "name": "John Doe",
- "phone": "6591234567",
- "avatar": "",
- "token": "20260405ABCDEFGHIJKLMN",
- "dob": "1990-05-02 00:00:00",
- "vehicleNo": "SBA1234X",
- "walletAmount": 120.5
}
}
}Retrieve a list of all users
| page | integer Page number |
| per_page | integer Number of items per page |
{- "ok": true,
- "total": 25,
- "page": 1,
- "data": [
- {
- "_id": "66337ada513dff7cb0219963",
- "name": "Tino",
- "password": "string",
- "dob": "1990-05-02T00:00:00.000Z",
- "phone": 827277157,
- "wallet_balance": 15931,
- "vehicle_license_plate": "123456",
- "vehicle_brand": "TESLA",
- "vehicle_model": "123456",
- "stripe_tokenized_cards": [
- "66337ba6b70e4d50370876aa"
], - "total_points": 1000,
- "membership_level": "66337ba6b70e4d50370876aa",
- "membership_level_name": "Gold",
- "plug_n_charge_enabled": false
}
]
}Update user's car information
| vehicle_license_plate required | string Vehicle license plate of the user |
| vehicle_brand required | string Brand of the vehicle |
| vehicle_model required | string Model of the vehicle |
{- "vehicle_license_plate": "ABC1234",
- "vehicle_brand": "Toyota",
- "vehicle_model": "Camry"
}{- "ok": true,
- "data": {
- "vehicle_license_plate": "ABC123",
- "vehicle_brand": "Toyota",
- "vehicle_model": "Camry"
}
}Retrieve the location and position user in list_queueing_users.
{- "ok": true,
- "data": [
- {
- "location": {
- "_id": "6331276a96ec3fa15d1cb0fc",
- "name": "The Vertex (Private Test)"
}, - "position": 0
}
]
}Start as guest
| device_id required | string Device id of the user |
| device_platform required | string Device Platform of the guest |
{- "device_id": "ABCD12344TTT",
- "device_platform": "android or ios"
}{- "login_token": "20241128ABCDEFGHIJKLMN"
}{- "ok": true,
- "data": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Tino",
- "password": "string",
- "dob": "1990-05-02T00:00:00.000Z",
- "phone": 827277157,
- "wallet_balance": 15931,
- "vehicle_license_plate": "123456",
- "vehicle_brand": "TESLA",
- "vehicle_model": "123456",
- "stripe_tokenized_cards": [
- "66337ba6b70e4d50370876aa"
], - "total_points": 1000,
- "membership_level": "66337ba6b70e4d50370876aa",
- "membership_level_name": "Gold",
- "plug_n_charge_enabled": false
}
}Retrieve the rewards of the currently logged-in user.
| reward_type_id | string Example: reward_type_id=665e8f15ebf7d56c133612ab Filter rewards by type |
| status | string Example: status=redeemed Filter rewards by status |
| page | integer Example: page=1 Page number for pagination |
| per_page | integer Example: per_page=10 Number of items per page for pagination |
{- "ok": true,
- "total": 5,
- "page": 1,
- "data": [
- {
- "_id": "60d9f1145b9e3a1c4f9d8a42",
- "reward_program_id": "60d9f1145b9e3a1c4f9d8a45",
- "reward_program_name": "Charge and Get Mystery Box",
- "value": 10,
- "value_type": "points",
- "reward_type_code": "mystery_box",
- "reward_type_name": "Mystery Box",
- "status": "new",
- "created_at": "2025-01-01T12:00:00Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "expiry_datetime": "2025-12-31T23:59:59Z",
- "user_id": "60d9f1145b9e3a1c4f9d8a46",
- "source": "charge_session",
- "source_id": "60d9f1145b9e3a1c4f9d8a47",
- "redeemed_at": "2025-01-01T12:00:00Z",
- "redeemed_by": "60d9f1145b9e3a1c4f9d8a47",
- "reward_program": {
- "_id": "60d9f1145b9e3a1c4f9d8a45",
- "name": "Charge and Get Mystery Box",
}
}
]
}Retrieve a specific reward of the currently logged-in user.
| reward_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the reward to retrieve. |
{- "ok": true,
- "data": {
- "_id": "60d9f1145b9e3a1c4f9d8a42",
- "reward_program_id": "60d9f1145b9e3a1c4f9d8a45",
- "reward_program_name": "Charge and Get Mystery Box",
- "value": 10,
- "value_type": "points",
- "reward_type_code": "mystery_box",
- "reward_type_name": "Mystery Box",
- "status": "new",
- "created_at": "2025-01-01T12:00:00Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "expiry_datetime": "2025-12-31T23:59:59Z",
- "user_id": "60d9f1145b9e3a1c4f9d8a46",
- "source": "charge_session",
- "source_id": "60d9f1145b9e3a1c4f9d8a47",
- "redeemed_at": "2025-01-01T12:00:00Z",
- "redeemed_by": "60d9f1145b9e3a1c4f9d8a47",
- "reward_program": {
- "_id": "60d9f1145b9e3a1c4f9d8a45",
- "name": "Charge and Get Mystery Box",
}
}
}Redeem a specific reward of the currently logged-in user.
| reward_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the reward to redeem. |
{- "ok": true,
- "msg": "Reward redeemed successfully"
}Retrieve the point history of the currently logged-in user.
| from_date | string <date> Example: from_date=2023-01-01 Start date for filtering points history |
| to_date | string <date> Example: to_date=2023-12-31 End date for filtering points history |
| page | integer Example: page=1 Page number for pagination |
| per_page | integer Example: per_page=10 Number of items per page for pagination |
{- "ok": true,
- "total": 20,
- "page": 1,
- "data": [
- {
- "_id": "60d9f1145b9e3a1c4f9d8a48",
- "user_id": "60d9f1145b9e3a1c4f9d8a49",
- "created_at": "2025-01-01T12:00:00Z",
- "points": 100,
- "source": "reward",
- "source_id": "60d9f1145b9e3a1c4f9d8a4a",
- "remark": "User earned points for a purchase.",
- "old_point": 500,
- "new_point": 600
}
]
}Retrieve the pending charging sessions of the currently logged-in user.
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}Retrieve charging sessions for the currently logged-in user with various filtering options.
| chargepoint_id | string Example: chargepoint_id=665e8f15ebf7d56c133612ab Filter by charge point ID (MongoDB ObjectId) |
| location_id | string Example: location_id=665e8f15ebf7d56c133612ab Filter by location ID (MongoDB ObjectId) |
| status | string Enum: "charging" "holding" "completed" "noshow" "canceled" Example: status=completed Filter by session status |
| type | string Enum: "adhoc" "reserved" "queue" Example: type=adhoc Filter by session type |
| from_date | string <date> Example: from_date=2024-01-01 Filter sessions from this date (inclusive, start of day) |
| to_date | string <date> Example: to_date=2024-01-31 Filter sessions until this date (inclusive, end of day) |
| skip | integer Default: 0 Number of records to skip (pagination) |
| limit | integer Default: 0 Example: limit=20 Maximum number of records to return (0 = no limit) |
| page | integer Default: 1 Example: page=1 Page number for pagination |
| per_page | integer Default: 10 Example: per_page=10 Number of records per page for pagination |
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}Retrieve charging sessions for the current user, including related transaction records.
| chargePointId | string Filter by charge point ID |
| type | string Enum: "adhoc" "reserved" Filter by session type |
| page | integer Default: 1 Page number |
| per_page | integer Default: 10 Items per page |
{- "ok": true,
- "data": [
- {
- "_id": "69af9032ce257fabd46cf014",
- "charge_point_name": "TinoCPO Test change",
- "session_started_at": "2026-03-10T03:29:54.432Z",
- "type": "adhoc",
- "location_name": "Jebson & Jessen",
- "status": "completed",
- "total_with_gst": 10.5,
- "Transactions": [
- {
- "transaction_id": "string",
- "User": "string",
- "gst": 9,
- "amount": 1000,
- "current_balance": 97929,
- "new_balance": 96893.5,
- "type": "subscription_payment",
- "status": "Approved",
- "payment_type": "wallet",
- "is_paid": true,
- "remarks": "",
- "promo_code_id": "string",
- "discount_value": 50,
- "total": 950,
- "total_with_gst": 1035.5,
- "subscription_id": "string",
- "createdAt": "2024-07-12T10:12:28.488Z",
- "updatedAt": "2024-07-12T10:12:28.488Z",
- "__v": 0
}
]
}
], - "total": 209,
- "page": 1
}Retrieve queue history for the current user from queueing_charging, including cancelled and missed queue records. Each item can include a mapped ChargeSession when the queue entry has a related charge_session_id.
| location_id | string Example: location_id=696869d231454e612bbdf207 Filter by location ID |
| status | string Enum: "activated" "cancelled" "missed" Example: status=cancelled Filter queue records by queue status |
| from_date | string <date> Example: from_date=2026-04-01 Filter queue records from this date (inclusive, start of day) |
| to_date | string <date> Example: to_date=2026-04-18 Filter queue records until this date (inclusive, end of day) |
| page | integer Default: 1 Example: page=1 Page number for pagination |
| per_page | integer Default: 10 Example: per_page=10 Number of records per page for pagination |
{- "ok": true,
- "total": 46,
- "page": 1,
- "per_page": 20,
- "data": [
- {
- "_id": "69dcb90b14ac228ec59c4d79",
- "user_id": "66337ada513dff7cb0219963",
- "location_id": "696869d231454e612bbdf207",
- "Location": {
- "_id": "696869d231454e612bbdf207",
- "name": "An test Location 1",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore 1",
- "latitude": 1.3483,
- "longitude": 103.6831
}, - "status": "cancelled",
- "join_at": "2026-04-13T09:36:11.084Z",
- "join_from": "mobile",
- "charge_session_id": null,
- "session_started_at": null,
- "user_name": "Tino Staging",
- "user_phone": "65827277157",
- "cancelled_at": "2026-04-13T09:49:21.878Z",
- "cancelled_from": "mobile",
- "missed_at": null,
- "ChargeSession": null
}, - {
- "_id": "69af8e258e328b6d38ebd37e",
- "user_id": "66337ada513dff7cb0219963",
- "location_id": "655da4b5b659e4ea4e5c5009",
- "Location": {
- "_id": "655da4b5b659e4ea4e5c5009",
- "name": "Bishopsgate Residences 36",
- "address": "18 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3334697,
- "longitude": 103.7022473
}, - "status": "activated",
- "join_at": "2026-03-10T03:21:09.251Z",
- "join_from": "mobile",
- "charge_session_id": "69af9032ce257fabd46cf014",
- "session_started_at": "2026-03-10T03:29:54.449Z",
- "user_name": "Tino Staging",
- "user_phone": "827277157",
- "ampeco_session_id": 202578,
- "charger_name": "TinoCPO Test change",
- "cancelled_at": null,
- "cancelled_from": null,
- "missed_at": null,
- "ChargeSession": {
- "_id": "69af9032ce257fabd46cf014",
- "status": "completed",
- "session_started_at": "2026-03-10T03:29:53.808Z",
- "session_stopped_at": "2026-03-10T03:31:18.285Z",
- "total": 10,
- "total_with_gst": 10.9,
- "charging_fee": 10,
- "charging_fee_with_gst": 10.9,
- "Location": {
- "_id": "655da4b5b659e4ea4e5c5009",
- "name": "Bishopsgate Residences 36",
- "address": "18 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3334697,
- "longitude": 103.7022473
}, - "Transactions": [
- {
- "_id": "69af91835e0800cf485fba39",
- "amount": 10.9,
- "status": "Approved"
}
], - "Evse": {
- "_id": "67dd4256d3aaf9a06257c858",
- "max_a": "32",
- "max_p": "32000",
- "max_v": "400",
- "floor": "B1",
- "name": "TinoCPO",
- "model": "Wallbox Commander2",
- "lot_number": "TinoCPO",
- "access_type": "public"
}
}
}
]
}Pay a specific charging session of the currently logged-in user.
| session_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the charging session to pay. |
| payment_method | string Payment method to use (e.g., wallet, card) |
| card_id | string Card ID to use if payment_method is card |
{- "payment_method": "wallet",
- "card_id": "card_123456789"
}{- "ok": true,
- "msg": "Make payment successfully.",
- "data": {
- "transactionId": "665e8f15ebf7d56c133612ab"
}
}Retrieve complete charging statistics including historical data, financial breakdown, and usage patterns for the current user in a single API call.
| type | string Default: "week" Enum: "week" "month" "year" Example: type=week Time period for statistics |
{- "ok": true,
- "data": {
- "totalKwh": 0.016,
- "avgKWhPerSession": 0.003,
- "totalKWhChangePercentage": 45.45,
- "avgKWhPerSessionChangePercentage": -51.52,
- "chartData": [
- {
- "period": "Week1",
- "value": 0.01
}, - {
- "period": "Week2",
- "value": 0.02
}, - {
- "period": "Week3",
- "value": 0.03
}, - {
- "period": "Week4",
- "value": 0.04
}
], - "mostUsedStations": [
- {
- "rank": 1,
- "name": "TinoCPO Test change",
- "numberOfSessions": 6,
- "totalKwh": 0.016
}
], - "financialBreakdown": {
- "totalSpent": 65.51,
- "averageCostPerkwh": 4.09,
- "totalIdlingFeeWithGst": 0.11,
- "cossOverFee": 0
}, - "chargingPatterns": {
- "totalSessions": 6,
- "totalDuration": "3h 39min",
- "averageTimeCharging": "0h 36min"
}
}
}Retrieve the transactions of the currently logged-in user.
| month | integer [ 1 .. 12 ] Example: month=1 Month for filtering transactions (1-12) |
| year | integer [ 2000 .. 2100 ] Example: year=2023 Year for filtering transactions (e.g., 2023) |
| from_date | string <date> Example: from_date=2023-01-01 Start date for filtering transactions |
| to_date | string <date> Example: to_date=2023-12-31 End date for filtering transactions |
| status | string Example: status=completed Filter transactions by status (e.g., completed, pending, failed, paid, unpaid) |
| type | string Example: type=charge_session Filter transactions by type (e.g., charge_session) |
| charge_session_id | string Example: charge_session_id=665e8f15ebf7d56c133612ab ID of the charge session to filter transactions (must be a valid ObjectId) |
| page | integer Example: page=1 Page number for pagination |
| per_page | integer Example: per_page=10 Number of items per page for pagination |
{- "ok": true,
- "total": 20,
- "page": 1,
- "data": [
- {
- "transaction_id": "string",
- "User": "string",
- "gst": 9,
- "amount": 1000,
- "current_balance": 97929,
- "new_balance": 96893.5,
- "type": "subscription_payment",
- "status": "Approved",
- "payment_type": "wallet",
- "is_paid": true,
- "remarks": "",
- "promo_code_id": "string",
- "discount_value": 50,
- "total": 950,
- "total_with_gst": 1035.5,
- "subscription_id": "string",
- "createdAt": "2024-07-12T10:12:28.488Z",
- "updatedAt": "2024-07-12T10:12:28.488Z",
- "__v": 0
}
]
}Pay a specific transaction of the currently logged-in user.
| transaction_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the transaction to pay. |
| payment_method | string Payment method to use (e.g., wallet, card) |
| card_id | string Card ID to use if payment_method is card |
{- "payment_method": "wallet",
- "card_id": "card_123456789"
}{- "ok": true,
- "msg": "Transaction paid successfully",
- "card_id": "card_123456789"
}Retrieve the outstanding payments of the currently logged-in user.
{- "ok": true,
- "data": {
- "total_count": 2,
- "total_amount": 50.75,
- "charge_sessions": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}
}Accepts an arbitrary payload and writes it to the server log for the logged-in user. Requires Authorization token.
{ }{- "ok": true
}Returns the authenticated user's profile.
This endpoint requires Authorization token.
plug_n_charge_enabled is always present and coerced to a boolean.
{- "ok": true,
- "data": {
- "_id": "665e8f15ebf7d56c133612ab",
- "name": "John Doe",
- "phone": "+6591234567",
- "wallet_balance": 5000,
- "vehicle_license_plate": "ABC123",
- "vehicle_brand": "Toyota",
- "vehicle_model": "Camry",
- "gender": "male",
- "address": "1 Marina Bay",
- "plug_n_charge_enabled": false,
- "percentage_profile_completion": 70,
- "sessions_count": 12
}
}Deletes a single notification via the Notification service. Requires Authorization token.
| notification_id required | string |
{- "notification_id": "string"
}{- "ok": true,
- "msg": "Notification deleted"
}Marks a single notification as read via the Notification service. Requires Authorization token.
| notification_id required | string |
{- "notification_id": "string"
}{- "ok": true,
- "msg": "Notification read"
}Marks all of a user's notifications as read via the Notification service. Requires Authorization token.
| user_id required | string |
{- "user_id": "string"
}{- "ok": true,
- "msg": "All notifications read"
}Uploads and sets the logged-in user's profile avatar image. Requires Authorization token.
| avatar | string <binary> |
{- "ok": true,
- "msg": "Profile avatar updated!",
- "data": { }
}Update the authenticated user's profile. All fields are optional; only the fields provided in the request body are updated. This endpoint requires Authorization token.
| name | string Display name of the user |
| dob | string Date of birth |
| vehicle_brand | string Brand of the vehicle |
| vehicle_model | string Model of the vehicle |
| vehicle_license_plate | string Vehicle license plate (alias, |
| password | string New password |
| gender | string |
| address | string |
| plug_n_charge_enabled | boolean Enable or disable Plug & Charge for the user |
{- "name": "John Doe",
- "dob": "1990-01-01",
- "vehicle_brand": "Toyota",
- "vehicle_model": "Camry",
- "vehicle_license_plate": "ABC1234",
- "password": "Secret123",
- "gender": "male",
- "address": "1 Marina Bay",
- "plug_n_charge_enabled": true
}{- "ok": true,
- "msg": "Profile name updated",
- "data": {
- "name": "John Doe",
- "phone": "+6591234567",
- "avatar": "",
- "token": "a1b2c3d4",
- "dob": "1990-01-01 00:00:00",
- "vehicleNo": "ABC123",
- "walletAmount": 5000,
- "vehicle_brand": "Toyota",
- "vehicle_model": "Camry",
- "gender": "male",
- "address": "1 Marina Bay",
- "plug_n_charge_enabled": true
}
}Checks the supplied password against the logged-in user's stored password. Requires Authorization token.
| password | string |
{- "password": "string"
}{- "ok": true,
- "msg": "string"
}Verify OTP for the authenticated user's current email,
then set email_verified=true for that user.
This endpoint requires Authorization token.
| otp required | string OTP code sent from |
{- "otp": "123456"
}{- "ok": true,
- "msg": "Email verified successfully"
}Send OTP code via SMS for phone-based authentication (login or registration).
| phone required | string Singapore phone number. Accepts either 8 digits (old app) or full 65XXXXXXXX format. |
{- "ok": true,
- "msg": "OTP sent"
}Verify OTP for phone login.
is_new_account to determine whether to show onboarding screens.| phone required | string Singapore phone number. Accepts either 8 digits (old app) or full 65XXXXXXXX format. |
| otp required | string OTP code sent by /send/otp. |
| fcm_token | string Optional device push token. |
{- "phone": "91234567",
- "otp": "123456",
- "fcm_token": "fcm_device_token"
}{- "ok": true,
- "msg": "OTP verified and login success",
- "data": {
- "phone": "6591234567",
- "has_account": true,
- "is_new_account": false,
- "user": {
- "_id": "67f1234567890abcde123456",
- "name": "John Doe",
- "phone": "6591234567",
- "avatar": "",
- "token": "20260405ABCDEFGHIJKLMN",
- "dob": "1990-05-02 00:00:00",
- "vehicleNo": "SBA1234X",
- "walletAmount": 120.5
}
}
}Creates the admin/CPO account with name, email, role and password. For "Seeding Partner" roles a profit-sharing percentage and location assignment are required.
| name required | string |
| email required | string |
| role required | string |
| password required | string |
| retypePassword required | string |
| profit_sharing_sp | number Required only for Seeding Partner (0-100) |
| Location | string Location id |
{- "name": "string",
- "email": "string",
- "role": "string",
- "password": "string",
- "retypePassword": "string",
- "profit_sharing_sp": 0,
- "Location": "string"
}{- "ok": true,
- "msg": "string",
- "data": {
- "_id": "string",
- "role": "string"
}
}Creates a company from the request body and assigns it to the admin identified by the id query parameter.
| id required | string Admin id to assign the company to |
| property name* additional property | any |
{ }{- "ok": true,
- "msg": "string",
- "data": {
- "_id": "string"
}
}Creates an Ampeco location and a local Location record for the admin identified by the id query parameter.
| id required | string Admin (CPO) id |
| property name* additional property | any |
{ }{- "ok": true,
- "msg": "string",
- "data": {
- "_id": "string"
}
}Saves electricity information to the company belonging to the admin identified by the id query parameter.
| id required | string Admin id |
| property name* additional property | any |
{ }{- "ok": true,
- "msg": "string",
- "data": {
- "_id": "string"
}
}Saves billing information to the company belonging to the admin identified by the id query parameter.
| id required | string Admin id |
| property name* additional property | any |
{ }{- "ok": true,
- "msg": "string",
- "data": {
- "_id": "string"
}
}Authenticates an admin/CPO account by email and password. Superadmins are logged into the session; non-superadmins receive a redirect to the CPO dashboard backend.
| email required | string |
| password required | string |
{- "password": "string"
}{- "ok": true,
- "msg": "Login Success",
}Sends either an OTP (method=otp) or a reset link to the user's email for the forgot-password flow. Public route (no token required).
| email required | string |
| method | string Enum: "otp" "link" |
{- "ok": true
}Verifies the OTP and marks the logged-in user's email as verified. Requires Authorization token.
| email required | string |
| otp required | string |
{- "email": "string",
- "otp": "string"
}{- "ok": true,
- "msg": "Email verified successfully"
}Sends an OTP to a new email for the logged-in user, ensuring the email is not already in use by another account. Requires Authorization token.
| email required | string |
{- "email": "string"
}{- "ok": true,
- "msg": "OTP sent"
}Validates an email + OTP pair against the User service. Public route.
| email required | string |
| otp required | string |
{- "email": "string",
- "otp": "string"
}{- "ok": true
}Authenticates a user with email/password, issues a login token, records a sign-in log and returns the user profile. Public route (no token required).
| email required | string |
| password required | string |
| fcm_token | string Optional device FCM token |
{- "email": "string",
- "password": "string",
- "fcm_token": "string"
}{- "ok": true,
- "msg": "Login Success",
- "data": {
- "_id": "string",
- "name": "string",
- "email": "string",
- "phone": "string",
- "token": "string",
- "walletAmount": 0
}
}Creates a new user after checking email/phone uniqueness, then pushes the customer to NetSuite. Public route (no token required).
| email required | string |
| password required | string |
| name required | string |
| phone required | string |
| vehicle_no required | string |
| car_brand required | string |
| car_model required | string |
| dob required | string Date of birth |
{- "email": "string",
- "password": "string",
- "name": "string",
- "phone": "string",
- "vehicle_no": "string",
- "car_brand": "string",
- "car_model": "string",
- "dob": "string"
}{- "ok": true,
- "msg": "User created",
- "data": { }
}Sends a 2FA verification code by SMS to the given phone number (Singapore numbers auto-prefixed with 65). Public route.
| phone required | string |
| purpose | string Default: "register" Enum: "register" "login" |
{- "ok": true,
- "msg": "OTP sent"
}Updates the password for the given email when new_password matches confirm_password (used in the forgot-password flow). Public route.
| email required | string |
| new_password required | string |
| confirm_password required | string |
{- "email": "string",
- "new_password": "string",
- "confirm_password": "string"
}{- "ok": true,
- "msg": "Password updated!"
}Endpoint hit when a user clicks the emailed verification link; marks the email verified and renders an HTML confirmation page. Public route.
| token required | string |
{- "ok": false,
- "msg": "Something went wrong, please contact CS for supporting."
}Verifies a phone OTP, creating a new account if the phone is unknown, then performs login and returns the user profile. Public route.
| phone required | string |
| otp required | string |
| fcm_token | string |
{- "phone": "string",
- "otp": "string",
- "fcm_token": "string"
}{- "ok": true,
- "msg": "string",
- "data": {
- "phone": "string",
- "has_account": true,
- "user": { }
}
}Get all merchant
| keyword | string Get merchants by name, code |
| page | integer Page number |
| per_page | integer Number of items per page |
{- "ok": true,
- "total": 25,
- "page": 1,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "name": "Merchant one"
}
]
}Get all subscription plans
| keyword | string Get subscription plans by name or code |
| merchant_id | string Merchant ID |
| merchant_code | string Merchant code |
| status | string Enum: "active" "inactive" "deleted" Status of the subscription plan |
| per_page | integer Number of items per page |
| page | integer Page number |
| deleteAt | string <date-time> Deletion date |
{- "ok": true,
- "total": 25,
- "page": 1,
- "data": [
- {
- "_id": "668c0cf8c6be695249b6a54b",
- "code": "TINOOOpo",
- "name": "VIP User",
- "description": "WHQ-1",
- "status": "active",
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "prices": [
- {
- "name": "1 month",
- "code": "1_MONTH",
- "price": 100,
- "original_price": 100
}
], - "deletedAt": "2024-07-08T16:00:04.284Z"
}
]
}Get a subscription plan by ID
| id required | string ID of the subscription plan to get |
{- "ok": true,
- "data": {
- "_id": "668c0cf8c6be695249b6a54b",
- "code": "TINOOOpo",
- "name": "VIP User",
- "description": "WHQ-1",
- "status": "active",
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "prices": [
- {
- "name": "1 month",
- "code": "1_MONTH",
- "price": 100,
- "original_price": 100
}
], - "deletedAt": "2024-07-08T16:00:04.284Z"
}
}Subscribe to a subscription plan. The request is rejected when the authenticated user already has a same-location effective subscription. Effective checks ignore deleted records and match records with status=active or records where subscribe_to is non-null and still in the future.
| subscription_plan_id required | string ID of the subscription plan |
| location_id required | string ID of the location that is used for this subscription. Required for all regular purchases via /subscribe. A null/global-scope location_id is accepted only through the activation-code flow (POST /v1/subscriptions/activate-by-code), not through this endpoint. |
| user_id | string ID of the user |
object Plan price details | |
| active_date | string <date-time> Activation date |
| is_auto_renew | boolean Enable automatic renewal after this subscription becomes active. Defaults to false. |
{- "subscription_plan_id": "6555e1982a447d5393551866",
- "location_id": "66337ada513dff7cb0219963",
- "user_id": "66b176eac77dae25d567ec2",
- "plan_price": {
- "name": "Standard",
- "price": 3990
}, - "active_date": "2024-10-15T08:00:00Z",
- "is_auto_renew": false
}{- "ok": true,
- "data": { }
}Get all subscriptions
| subscription_plan_id | string Subscription plan ID |
| merchant_id | string Merchant ID |
| status | string Subscription status |
| per_page | integer Number of items per page |
| page | integer Page number |
| active_from | string <date> Active from date |
| active_to | string <date> Active to date |
{- "ok": true,
- "total": 25,
- "page": 1,
- "data": [
- {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
]
}Make a payment for a subscription
| subscription_id | string Subscription ID |
| payment_type | string Enum: "wallet" "card" "abapay" Payment type |
| card_id | string if |
| promo_code_id | string Promo code ID |
{- "subscription_id": "string",
- "payment_type": "wallet",
- "card_id": "66f77bc453598b2450dd2a0a",
- "promo_code_id": "string"
}{- "ok": true,
- "msg": "Subscription already paid",
- "data": {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
}Activate a subscription
| subscription_id required | string Subscription ID |
{- "ok": true,
- "data": {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
}Toggles recurring renewal for one owned, active, paid, unexpired subscription whose plan supports renewal.
| subscription_id required | string Subscription ID |
| is_auto_renew required | boolean |
{- "is_auto_renew": true
}{- "ok": true,
- "msg": "string"
}Deactivate a subscription
| subscription_id required | string Subscription ID |
{- "ok": true,
- "data": {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
}{- "ok": true,
- "data": {
- "subscription_detail": {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "name": "Merchant one"
}, - "subscription_consumption": {
- "total_energy": 0,
- "total_amount": 0,
- "total_session": 0,
- "total_duration": 0
}
}
}| subscription_plan_id | string Default: "6555e1982a447d5393551866" Filter by subscription plan ID (UUID) |
| page | integer Default: 1 Page number |
| per_page | integer Default: 100 Number records/page |
{- "ok": true,
- "data": [
- {
- "name": "Tribecar",
- "longitude": 103.8978969,
- "latitude": 1.3257982,
- "status": "active",
- "ampeco_location_id": 84,
- "description": "51 Ubi Ave 1, Singapore 408933",
- "address": "51 Ubi Ave 1, Singapore 408933",
- "region": "East",
- "city": "Singapore",
- "postal": "408933",
- "country": "SG",
- "image": "apj3sMi4FBOdBhs6dA.jpg",
- "ChargePoints": [
- "string"
], - "is_enabled": true,
- "is_queue_enabled": true,
- "createdAt": "2022-11-13T14:46:08.709Z",
- "updatedAt": "2022-11-13T14:46:08.709Z",
- "__v": 0
}
], - "msg": "",
- "total": 30,
- "page": 1,
- "per_page": 100
}| id required | string Subscription ID (UUID) |
| page | integer Default: 1 Page number |
| per_page | integer Default: 100 Number records/page |
{- "ok": true,
- "data": [
- {
- "transaction_id": "string",
- "User": "string",
- "gst": 9,
- "amount": 1000,
- "current_balance": 97929,
- "new_balance": 96893.5,
- "type": "subscription_payment",
- "status": "Approved",
- "payment_type": "wallet",
- "is_paid": true,
- "remarks": "",
- "promo_code_id": "string",
- "discount_value": 50,
- "total": 950,
- "total_with_gst": 1035.5,
- "subscription_id": "string",
- "createdAt": "2024-07-12T10:12:28.488Z",
- "updatedAt": "2024-07-12T10:12:28.488Z",
- "__v": 0
}
], - "msg": "",
- "total": 30,
- "page": 1,
- "per_page": 100
}Checks whether a global/no-location activation code is redeemable.
| code required | string Activation Code |
| subscription_plan_id required | string Subscription Plan ID |
{- "ok": true,
- "data": [
- {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
], - "msg": ""
}Redeems a global/no-location activation-code subscription. The request is rejected if the user already has an effective global subscription. Effective checks ignore deleted records and match records with status=active or records where subscribe_to is non-null and still in the future. Location-bound effective subscriptions can coexist with the redeemed global subscription.
| code | string Activation Code |
| subscription_plan_id | string Subscription Plan ID |
{- "code": "string",
- "subscription_plan_id": "string"
}{- "ok": true,
- "data": [
- {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
], - "msg": ""
}| id required | string The subscription ID (MongoDB ObjectId) |
| payment_type | string Enum: "wallet" "card" "abapay" The type of payment |
| card_id | string The ID of the card used for payment (mongoDB ObjectId). Required with type=card |
{- "payment_type": "wallet",
- "card_id": "5f7e8f15ebf7d56c133612ab"
}{- "ok": true,
- "data": {
- "subscription_id": "66b78456642444e4b596a9db",
- "renewed_at": "2024-10-15T08:00:00Z"
}, - "msg": "Subscription renewed successfully"
}This endpoint checks the renewal information for a subscription. It fetches the subscription based on the provided subscription ID, calculates the renewal date, and returns the price and price with GST.
| subscription_id required | string The ID of the subscription to check |
{- "ok": true,
- "data": {
- "subscription_to": "2024-11-15T23:59:59.999Z",
- "price": 3990,
- "price_with_gst": 4389
}
}{- "ok": true,
- "data": {
- "subscription_detail": {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "name": "Merchant one"
}, - "subscription_consumption": {
- "total_energy": 0,
- "total_amount": 0,
- "total_session": 0,
- "total_duration": 0
}
}
}| subscription_plan_id | string Default: "6555e1982a447d5393551866" Filter by subscription plan ID (UUID) |
| page | integer Default: 1 Page number |
| per_page | integer Default: 100 Number records/page |
{- "ok": true,
- "data": [
- {
- "name": "Tribecar",
- "longitude": 103.8978969,
- "latitude": 1.3257982,
- "status": "active",
- "ampeco_location_id": 84,
- "description": "51 Ubi Ave 1, Singapore 408933",
- "address": "51 Ubi Ave 1, Singapore 408933",
- "region": "East",
- "city": "Singapore",
- "postal": "408933",
- "country": "SG",
- "image": "apj3sMi4FBOdBhs6dA.jpg",
- "ChargePoints": [
- "string"
], - "is_enabled": true,
- "is_queue_enabled": true,
- "createdAt": "2022-11-13T14:46:08.709Z",
- "updatedAt": "2022-11-13T14:46:08.709Z",
- "__v": 0
}
], - "msg": "",
- "total": 30,
- "page": 1,
- "per_page": 100
}| id required | string Subscription ID (UUID) |
| page | integer Default: 1 Page number |
| per_page | integer Default: 100 Number records/page |
{- "ok": true,
- "data": [
- {
- "transaction_id": "string",
- "User": "string",
- "gst": 9,
- "amount": 1000,
- "current_balance": 97929,
- "new_balance": 96893.5,
- "type": "subscription_payment",
- "status": "Approved",
- "payment_type": "wallet",
- "is_paid": true,
- "remarks": "",
- "promo_code_id": "string",
- "discount_value": 50,
- "total": 950,
- "total_with_gst": 1035.5,
- "subscription_id": "string",
- "createdAt": "2024-07-12T10:12:28.488Z",
- "updatedAt": "2024-07-12T10:12:28.488Z",
- "__v": 0
}
], - "msg": "",
- "total": 30,
- "page": 1,
- "per_page": 100
}Checks whether a global/no-location activation code is redeemable.
| code required | string Activation Code |
| subscription_plan_id required | string Subscription Plan ID |
{- "ok": true,
- "data": [
- {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
], - "msg": ""
}Redeems a global/no-location activation-code subscription. The request is rejected if the user already has an effective global subscription. Effective checks ignore deleted records and match records with status=active or records where subscribe_to is non-null and still in the future. Location-bound effective subscriptions can coexist with the redeemed global subscription.
| code | string Activation Code |
| subscription_plan_id | string Subscription Plan ID |
{- "code": "string",
- "subscription_plan_id": "string"
}{- "ok": true,
- "data": [
- {
- "_id": "668e541d135096d2c3b2f59c",
- "subscription_plan_id": "668a960adb4cd9bf088e5dc1",
- "subscription_plan_code": "DEV1PLAN",
- "subscription_plan_name": "Plan of DEV1",
- "user_id": "667ae4df75ed5e17162fdcea",
- "merchant_id": null,
- "subscribe_from": "2024-07-10T09:31:30.000Z",
- "subscribe_to": "2025-07-10T09:31:30.000Z",
- "subscription_time": null,
- "quotation": {
- "max_duration_per_day": 2,
- "max_duration_per_month": 60,
- "max_energy_per_day": 0,
- "max_energy_per_month": 100
}, - "active_date": null,
- "subscription_price": null,
- "promo_code": null,
- "discounted_price": 0,
- "payable_price": null,
- "transaction_id": null,
- "status": "active",
- "payment_status": "paid",
- "is_auto_renew": false,
- "location_id": "66337ada513dff7cb0219963",
- "location": {
- "_id": "66337ada513dff7cb0219963",
- "name": "Watt Hub",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3483,
- "longitude": 103.6831
}
}
], - "msg": ""
}| id required | string The subscription ID (MongoDB ObjectId) |
| payment_type | string Enum: "wallet" "card" "abapay" The type of payment |
| card_id | string The ID of the card used for payment (mongoDB ObjectId). Required with type=card |
{- "payment_type": "wallet",
- "card_id": "5f7e8f15ebf7d56c133612ab"
}{- "ok": true,
- "data": {
- "subscription_id": "66b78456642444e4b596a9db",
- "renewed_at": "2024-10-15T08:00:00Z"
}, - "msg": "Subscription renewed successfully"
}This endpoint checks the renewal information for a subscription. It fetches the subscription based on the provided subscription ID, calculates the renewal date, and returns the price and price with GST.
| subscription_id required | string The ID of the subscription to check |
{- "ok": true,
- "data": {
- "subscription_to": "2024-11-15T23:59:59.999Z",
- "price": 3990,
- "price_with_gst": 4389
}
}| keyword | string Search by keyword - code, name, ... |
| promo_type | string Enum: "Subscription" "FeePayment" Filter by promo type |
| status | string Enum: "active" "inactive" "deleted" Filter by status |
| is_used | boolean Filter by is used |
| merchant_id | string Filter by merchant id |
| page | integer The page number. |
| per_page | integer The numbers of items to return. |
{- "ok": true,
- "total": 25,
- "page": 1,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "program_id": "665e8f15ebf7d56c133612ab",
- "name": "Free 1 month",
- "merchant_id": "665e8f15ebf7d56c133612ab",
- "merchant_name": "Merchant ABC Ltd.",
- "description": "This is a description",
- "promo_type": "Subscription",
- "discount_value": 100,
- "discount_type": "percent",
- "max_discount": 50,
- "max_discount_type": "fixed",
- "expiry_date": "2021-07-31T00:00:00.000Z",
- "status": "active",
- "created_at": "2021-07-01T00:00:00.000Z",
- "updated_at": "2021-07-01T00:00:00.000Z",
- "activated_at": "2021-07-01T00:00:00.000Z",
- "activated_by": "665e8f15ebf7d56c133612ab",
- "activated_by_name": "User ABC"
}
]
}| code required | string Example: code=PROMOV3O code that want to search |
{- "ok": true,
- "data": {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "program_id": "665e8f15ebf7d56c133612ab",
- "name": "Free 1 month",
- "merchant_id": "665e8f15ebf7d56c133612ab",
- "merchant_name": "Merchant ABC Ltd.",
- "description": "This is a description",
- "promo_type": "Subscription",
- "discount_value": 100,
- "discount_type": "percent",
- "max_discount": 50,
- "max_discount_type": "fixed",
- "expiry_date": "2021-07-31T00:00:00.000Z",
- "status": "active",
- "created_at": "2021-07-01T00:00:00.000Z",
- "updated_at": "2021-07-01T00:00:00.000Z",
- "activated_at": "2021-07-01T00:00:00.000Z",
- "activated_by": "665e8f15ebf7d56c133612ab",
- "activated_by_name": "User ABC"
}
}{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "program_id": "665e8f15ebf7d56c133612ab",
- "name": "Free 1 month",
- "merchant_id": "665e8f15ebf7d56c133612ab",
- "merchant_name": "Merchant ABC Ltd.",
- "description": "This is a description",
- "promo_type": "Subscription",
- "discount_value": 100,
- "discount_type": "percent",
- "max_discount": 50,
- "max_discount_type": "fixed",
- "expiry_date": "2021-07-31T00:00:00.000Z",
- "status": "active",
- "created_at": "2021-07-01T00:00:00.000Z",
- "updated_at": "2021-07-01T00:00:00.000Z",
- "activated_at": "2021-07-01T00:00:00.000Z",
- "activated_by": "665e8f15ebf7d56c133612ab",
- "activated_by_name": "User ABC"
}
]
}| id required | string Promo code ID |
Calculate discount request body
| invoice_type | string Type of invoice |
| amount | number Amount for which discount is to be calculated |
{- "invoice_type": "Subscription",
- "amount": 100
}{- "ok": true,
- "data": {
- "original_price": 100,
- "discounted_price": 10,
- "discounted_type": "percent",
- "discounted_value": 10,
- "final_price": 90
}
}| id required | string Promo code ID |
Mark used request body
| transaction_id | string Transaction id |
{- "transaction_id": "666b176eac77dae25d567ec2"
}{- "ok": true,
- "msg": "Used ${number} promo codes"
}| keyword | string Keyword to search promo programs |
| merchant_id | string Merchant ID |
| promo_type | string Promo type |
| used_codes | integer Number of used codes |
| start_date | string <date> Start date |
| end_date | string <date> End date |
| per_page | integer >= 1 Items per page |
| page | integer >= 1 Page number |
{- "ok": true,
- "total": 25,
- "page": 1,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "merchant_id": "665e8f15ebf7d56c133612ab",
- "name": "Free 1 month",
- "description": "This program is for new user only",
- "promo_type": "Subscription",
- "discount_value": 100,
- "discount_type": "percent",
- "max_discount": 50,
- "max_discount_type": "fixed",
- "start_date": "2021-07-01T00:00:00.000Z",
- "end_date": "2021-07-31T00:00:00.000Z",
- "status": "active",
- "created_at": "2021-07-01T00:00:00.000Z",
- "updated_at": "2021-07-01T00:00:00.000Z",
- "number_of_codes": 10,
- "used_codes": 5
}
]
}| promo_program_id required | string Promo program ID |
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "code": "M1234",
- "merchant_id": "665e8f15ebf7d56c133612ab",
- "name": "Free 1 month",
- "description": "This program is for new user only",
- "promo_type": "Subscription",
- "discount_value": 100,
- "discount_type": "percent",
- "max_discount": 50,
- "max_discount_type": "fixed",
- "start_date": "2021-07-01T00:00:00.000Z",
- "end_date": "2021-07-31T00:00:00.000Z",
- "status": "active",
- "created_at": "2021-07-01T00:00:00.000Z",
- "updated_at": "2021-07-01T00:00:00.000Z",
- "number_of_codes": 10,
- "used_codes": 5
}
]
}Returns active FAQs, optionally filtered by information category.
| category_id | string Filter FAQs by information category ID. |
{- "ok": true,
- "msg": "",
- "data": [
- {
- "category_id": "string",
- "category_name": "string",
- "id": "string",
- "question": "string",
- "answer": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}| amount | number Amount to topup |
{- "amount": 0
}{- "ok": true,
- "data": {
- "status": {
- "code": "string",
- "message": "string",
- "tran_id": "string"
}, - "description": "success",
- "qr_string": "00020101021230510016abaakhppxxx@abaa01157989728749832940208ABA Bank52040000530311654031005802KH5914GO EV Chargers6003N",
- "abapay_deeplink": "abamobilebank://ababank.com",
}
}Receives a payment status callback from ABA PayWay and forwards it to the Payment service.
Requires a transaction id (tran_id) in the body. This route is public (no Authorization token required).
| tran_id required | string ABA PayWay transaction id |
{- "tran_id": "string"
}{- "ok": true,
- "msg": "Transaction id is required"
}Updates the status of a payout request (awaiting/processing/paid) and notifies the requester by email. A transaction reference is required for processing/paid statuses. Requires update ACL.
| _id required | string |
| status required | string Enum: "awaiting" "processing" "paid" |
| transaction_id | string |
| remarks | string |
| confirm required | boolean |
{- "_id": "string",
- "status": "awaiting",
- "transaction_id": "string",
- "remarks": "string",
- "confirm": true
}{- "ok": true,
- "msg": "Payout updated"
}Creates a payout request for the logged-in admin. Requires a wallet balance of at least the minimum payout amount and all bank fields to be provided; resets the wallet balance to 0.
| confirm required | boolean |
| bank_account_number required | string |
| bank_account_holder_name required | string |
| bank_branch required | string |
| bank_name required | string |
| notify_email required | string |
{- "confirm": true,
- "bank_account_number": "string",
- "bank_account_holder_name": "string",
- "bank_branch": "string",
- "bank_name": "string",
- "notify_email": "string"
}{- "ok": true,
- "msg": "Payout submitted"
}Creates a Stripe customer if needed, links the card token, performs a check/refund and stores the tokenized card for the logged-in user. Requires Authorization token.
| card_token required | string |
| is_default | boolean |
| billing_adress1 | string |
| billing_adress2 | string |
| expiry_date | string |
| postal_code | string |
| country | string |
| mobile_holder | string |
| email_holder | string |
{- "card_token": "string",
- "is_default": true,
- "billing_adress1": "string",
- "billing_adress2": "string",
- "expiry_date": "string",
- "postal_code": "string",
- "country": "string",
- "mobile_holder": "string",
- "email_holder": "string"
}{- "ok": true,
- "msg": "Card added successfully",
- "data": { }
}Charges a small amount ($1) to validate the given card then automatically refunds it. Requires Authorization token.
| id required | string Tokenized card id |
{- "id": "string"
}{- "ok": true,
- "transaction_id": "string",
- "msg": "string"
}Marks the given card as the default payment card for the logged-in user. Requires Authorization token.
| id required | string Tokenized card id |
{- "id": "string"
}{- "ok": true,
- "data": [
- { }
]
}Returns the authenticated user's currently selected default payment method and card id. Defaults to the wallet when none is set. Requires Authorization token.
{- "ok": true,
- "data": {
- "type": "wallet",
- "card_id": "string"
}
}Sets the authenticated user's default payment method to a card or the wallet.
When type is card, card_id is required and must belong to the user.
Requires Authorization token.
| type required | string Enum: "wallet" "stripe" "abapay" "card" Payment method type |
| card_id | string Tokenized card id (required when type is |
{- "type": "wallet",
- "card_id": "string"
}{- "ok": true,
- "msg": "Default payment method updated"
}Deletes a tokenized card for the logged-in user and re-assigns the default card if needed. Requires Authorization token.
| id required | string Tokenized card id |
| is_default | boolean |
{- "id": "string",
- "is_default": true
}{- "ok": true,
- "data": [
- { }
]
}Charges the given card via the Payment service and credits the logged-in user's wallet. Requires Authorization token.
| amount required | number |
| card_id required | string |
{- "amount": 0,
- "card_id": "string"
}{- "ok": true,
- "msg": "Topup successful",
- "data": { }
}Validates the selected payment method (wallet minimum balance) and that the target EVSE is available/preparing before starting a session, storing the chosen payment method. Requires Authorization token.
| payment_method | string |
| card_id | string |
| charge_id | string |
| evse_id | string |
{- "payment_method": "string",
- "card_id": "string",
- "charge_id": "string",
- "evse_id": "string"
}{- "ok": true,
- "msg": "All paid"
}Checks that the logged-in user's selected payment method (wallet minimum balance or card pre-auth) is valid to start a charging session. Requires Authorization token.
{- "ok": true,
- "msg": "string"
}Returns the logged-in user's wallet balance in dollars along with placeholder loyalty fields. Requires Authorization token.
{- "ok": true,
- "data": {
- "amount": 0,
- "currency": "SGD",
- "point": 0,
- "reward": 0
}
}| amount | number Amount to topup |
{- "amount": 0
}{- "ok": true,
- "data": {
- "status": {
- "code": "string",
- "message": "string",
- "tran_id": "string"
}, - "description": "success",
- "qr_string": "00020101021230510016abaakhppxxx@abaa01157989728749832940208ABA Bank52040000530311654031005802KH5914GO EV Chargers6003N",
- "abapay_deeplink": "abamobilebank://ababank.com",
}
}Retrieve the charging status of all EVSEs associated with a specific location.
| location_id required | string Example: 6331276a96ec3fa15d1cb0fc The ID of the location to filter EVSEs by. |
{- "ok": true,
- "data": [
- [ ]
]
}Retrieve the location and position user in list_queueing_users.
{- "ok": true,
- "data": [
- {
- "location": {
- "_id": "6331276a96ec3fa15d1cb0fc",
- "name": "The Vertex (Private Test)"
}, - "position": 0
}
]
}Retrieve queue history for the current user from queueing_charging, including cancelled and missed queue records. Each item can include a mapped ChargeSession when the queue entry has a related charge_session_id.
| location_id | string Example: location_id=696869d231454e612bbdf207 Filter by location ID |
| status | string Enum: "activated" "cancelled" "missed" Example: status=cancelled Filter queue records by queue status |
| from_date | string <date> Example: from_date=2026-04-01 Filter queue records from this date (inclusive, start of day) |
| to_date | string <date> Example: to_date=2026-04-18 Filter queue records until this date (inclusive, end of day) |
| page | integer Default: 1 Example: page=1 Page number for pagination |
| per_page | integer Default: 10 Example: per_page=10 Number of records per page for pagination |
{- "ok": true,
- "total": 46,
- "page": 1,
- "per_page": 20,
- "data": [
- {
- "_id": "69dcb90b14ac228ec59c4d79",
- "user_id": "66337ada513dff7cb0219963",
- "location_id": "696869d231454e612bbdf207",
- "Location": {
- "_id": "696869d231454e612bbdf207",
- "name": "An test Location 1",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore 1",
- "latitude": 1.3483,
- "longitude": 103.6831
}, - "status": "cancelled",
- "join_at": "2026-04-13T09:36:11.084Z",
- "join_from": "mobile",
- "charge_session_id": null,
- "session_started_at": null,
- "user_name": "Tino Staging",
- "user_phone": "65827277157",
- "cancelled_at": "2026-04-13T09:49:21.878Z",
- "cancelled_from": "mobile",
- "missed_at": null,
- "ChargeSession": null
}, - {
- "_id": "69af8e258e328b6d38ebd37e",
- "user_id": "66337ada513dff7cb0219963",
- "location_id": "655da4b5b659e4ea4e5c5009",
- "Location": {
- "_id": "655da4b5b659e4ea4e5c5009",
- "name": "Bishopsgate Residences 36",
- "address": "18 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3334697,
- "longitude": 103.7022473
}, - "status": "activated",
- "join_at": "2026-03-10T03:21:09.251Z",
- "join_from": "mobile",
- "charge_session_id": "69af9032ce257fabd46cf014",
- "session_started_at": "2026-03-10T03:29:54.449Z",
- "user_name": "Tino Staging",
- "user_phone": "827277157",
- "ampeco_session_id": 202578,
- "charger_name": "TinoCPO Test change",
- "cancelled_at": null,
- "cancelled_from": null,
- "missed_at": null,
- "ChargeSession": {
- "_id": "69af9032ce257fabd46cf014",
- "status": "completed",
- "session_started_at": "2026-03-10T03:29:53.808Z",
- "session_stopped_at": "2026-03-10T03:31:18.285Z",
- "total": 10,
- "total_with_gst": 10.9,
- "charging_fee": 10,
- "charging_fee_with_gst": 10.9,
- "Location": {
- "_id": "655da4b5b659e4ea4e5c5009",
- "name": "Bishopsgate Residences 36",
- "address": "18 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3334697,
- "longitude": 103.7022473
}, - "Transactions": [
- {
- "_id": "69af91835e0800cf485fba39",
- "amount": 10.9,
- "status": "Approved"
}
], - "Evse": {
- "_id": "67dd4256d3aaf9a06257c858",
- "max_a": "32",
- "max_p": "32000",
- "max_v": "400",
- "floor": "B1",
- "name": "TinoCPO",
- "model": "Wallbox Commander2",
- "lot_number": "TinoCPO",
- "access_type": "public"
}
}
}
]
}{- "ok": true,
- "total": 3,
- "page": 1,
- "data": [
- {
- "_id": "60d9f1145b9e3a1c4f9d8a44",
- "code": "mystery_box",
- "name": "Mystery Box",
- "description": "A surprise box containing various rewards.",
- "status": "active",
- "created_at": "2025-01-01T12:00:00Z",
- "updated_at": "2025-01-02T12:00:00Z"
}
]
}Retrieve the rewards of the currently logged-in user.
| reward_type_id | string Example: reward_type_id=665e8f15ebf7d56c133612ab Filter rewards by type |
| status | string Example: status=redeemed Filter rewards by status |
| page | integer Example: page=1 Page number for pagination |
| per_page | integer Example: per_page=10 Number of items per page for pagination |
{- "ok": true,
- "total": 5,
- "page": 1,
- "data": [
- {
- "_id": "60d9f1145b9e3a1c4f9d8a42",
- "reward_program_id": "60d9f1145b9e3a1c4f9d8a45",
- "reward_program_name": "Charge and Get Mystery Box",
- "value": 10,
- "value_type": "points",
- "reward_type_code": "mystery_box",
- "reward_type_name": "Mystery Box",
- "status": "new",
- "created_at": "2025-01-01T12:00:00Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "expiry_datetime": "2025-12-31T23:59:59Z",
- "user_id": "60d9f1145b9e3a1c4f9d8a46",
- "source": "charge_session",
- "source_id": "60d9f1145b9e3a1c4f9d8a47",
- "redeemed_at": "2025-01-01T12:00:00Z",
- "redeemed_by": "60d9f1145b9e3a1c4f9d8a47",
- "reward_program": {
- "_id": "60d9f1145b9e3a1c4f9d8a45",
- "name": "Charge and Get Mystery Box",
}
}
]
}Retrieve a specific reward of the currently logged-in user.
| reward_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the reward to retrieve. |
{- "ok": true,
- "data": {
- "_id": "60d9f1145b9e3a1c4f9d8a42",
- "reward_program_id": "60d9f1145b9e3a1c4f9d8a45",
- "reward_program_name": "Charge and Get Mystery Box",
- "value": 10,
- "value_type": "points",
- "reward_type_code": "mystery_box",
- "reward_type_name": "Mystery Box",
- "status": "new",
- "created_at": "2025-01-01T12:00:00Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "expiry_datetime": "2025-12-31T23:59:59Z",
- "user_id": "60d9f1145b9e3a1c4f9d8a46",
- "source": "charge_session",
- "source_id": "60d9f1145b9e3a1c4f9d8a47",
- "redeemed_at": "2025-01-01T12:00:00Z",
- "redeemed_by": "60d9f1145b9e3a1c4f9d8a47",
- "reward_program": {
- "_id": "60d9f1145b9e3a1c4f9d8a45",
- "name": "Charge and Get Mystery Box",
}
}
}Redeem a specific reward of the currently logged-in user.
| reward_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the reward to redeem. |
{- "ok": true,
- "msg": "Reward redeemed successfully"
}Redeem a reward from the specified reward program using points. Only rewards that have not been assigned to any user (user_id is null) can be redeemed. The current logged-in user will be assigned the reward upon successful redemption.
| reward_program_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the reward program to redeem a reward from. |
{- "ok": true,
- "msg": "Reward redeemed successfully from program.",
- "data": {
- "reward_id": "665e8f15ebf7d56c133612ab",
- "added_points": 100
}
}Retrieve the point history of the currently logged-in user.
| from_date | string <date> Example: from_date=2023-01-01 Start date for filtering points history |
| to_date | string <date> Example: to_date=2023-12-31 End date for filtering points history |
| page | integer Example: page=1 Page number for pagination |
| per_page | integer Example: per_page=10 Number of items per page for pagination |
{- "ok": true,
- "total": 20,
- "page": 1,
- "data": [
- {
- "_id": "60d9f1145b9e3a1c4f9d8a48",
- "user_id": "60d9f1145b9e3a1c4f9d8a49",
- "created_at": "2025-01-01T12:00:00Z",
- "points": 100,
- "source": "reward",
- "source_id": "60d9f1145b9e3a1c4f9d8a4a",
- "remark": "User earned points for a purchase.",
- "old_point": 500,
- "new_point": 600
}
]
}Retrieve a paginated list of reward vendors. Supports filtering by name and code.
| name | string Example: name=Nike Filter by vendor name (supports partial match, case-insensitive) |
| code | string Example: code=nike Filter by vendor code (supports partial match, case-insensitive) |
| page | integer Default: 1 Page number for pagination. |
| per_page | integer Default: 10 Number of items per page. |
{- "ok": true,
- "total": 25,
- "page": 1,
- "per_page": 10,
- "data": [
- {
- "_id": "68fee1ceb94fe6465dfd7fc1",
- "name": "test",
- "code": "test",
- "description": "test",
- "createdAt": "2025-10-27T03:06:54.088Z",
- "updatedAt": "2025-10-27T04:40:51.415Z",
- "deletedAt": "2025-10-27T04:40:51.415Z"
}
]
}Retrieve a paginated list of reward categories.
| name | string Example: name=Text Filter by category name (supports partial match, case-insensitive). |
| code | string Example: code=text Filter by category code (supports partial match, case-insensitive). |
| page | integer Default: 1 Page number for pagination. |
| per_page | integer Default: 10 Number of items per page. |
{- "ok": true,
- "total": 25,
- "page": 1,
- "per_page": 10,
- "data": [
- {
- "_id": "68fee210b94fe6465dfd7fc2",
- "name": "test",
- "code": "test",
- "description": "test",
- "createdAt": "2025-10-27T03:08:00.116Z",
- "updatedAt": "2025-10-27T04:42:12.951Z",
- "deletedAt": "2025-10-27T04:42:12.951Z"
}
]
}Retrieve a paginated list of reward programs. Supports filtering by name, code, type, status, reward_type_id, vendor_id, and category_id, and location_id.
| name | string Example: name=Charge and Get Filter by reward program name (partial match, case-insensitive) |
| code | string Example: code=MYSTERYBOX2025 Filter by reward program code (partial match, case-insensitive) |
| type | string Enum: "points" "cashback" "mystery_box" "discount" "sign_up_bonus" "referral_bonus" Example: type=cashback Filter by reward program type |
| status | string Enum: "active" "inactive" "archived" Example: status=active Filter by reward program status |
| reward_type_id | string Example: reward_type_id=68fecfef9865f720ce4416f7 Filter by reward type ID (partial match, case-insensitive) |
| vendor_id | string Example: vendor_id=68ff2fe9946eb191f89574fd Filter by vendor ID (must be a valid ObjectId) |
| category_id | string Example: category_id=68fef6a32506e0a62fc34c9c Filter by category ID (must be a valid ObjectId) |
| location_id | string Example: location_id=6331276a96ec3fa15d1cb0fc Filter by location ID (must be a valid ObjectId) |
| is_favorite | boolean Example: is_favorite=true Filter to only favorite reward programs of the current user |
| page | integer Default: 1 Page number for pagination |
| per_page | integer Default: 10 Number of items per page |
{- "ok": true,
- "total": 25,
- "page": 1,
- "per_page": 10,
- "data": [
- {
- "_id": "692d5f4f660bbbe97b049f15",
- "name": "CF 1 voucher",
- "code": "MV2UFKLEXS",
- "description": "<p>Festive flavors of spiced gingerbread...</p>",
- "sort_description": "20% discount",
- "type": "voucher",
- "status": "expired",
- "reward_type_id": "68d0bf4099c3e69969ff6936",
- "start_date": "2025-12-01T00:00:00.000Z",
- "expiry_datetime": "2025-12-02T07:24:24.649Z",
- "redeem_by": "point",
- "redeem_value": 6,
- "locations": [
- "655da4b5b659e4ea4e5c5009"
], - "vendors": [
- "6925818738b8adf4652965fa"
], - "categories": [
- "691e7bd5b054463687632ff7"
], - "usage": "",
- "createdAt": "2025-12-01T09:26:39.523Z",
- "updatedAt": "2025-12-02T07:37:01.945Z",
- "remaining_count": 3,
- "total": 3,
- "redeemed_count": 3,
- "redeemed_value": 3,
- "expired_code": 0,
- "expired_value": 0,
- "total_value": 3,
- "unused_code": 0,
- "unused_value": 0
}
]
}Retrieve detailed information of a specific reward program for the authenticated user. Requires a valid reward_program_id (MongoDB ObjectId).
| reward_program_id required | string Example: 68fecfef9865f720ce4416f7 Reward program ID (must be a valid MongoDB ObjectId) |
{- "ok": true,
- "data": {
- "_id": "692d5f4f660bbbe97b049f15",
- "name": "CF 1 voucher",
- "code": "MV2UFKLEXS",
- "description": "<p>Festive flavors of spiced gingerbread...</p>",
- "sort_description": "20% discount",
- "type": "voucher",
- "status": "expired",
- "reward_type_id": "68d0bf4099c3e69969ff6936",
- "start_date": "2025-12-01T00:00:00.000Z",
- "expiry_datetime": "2025-12-02T07:24:24.649Z",
- "redeem_by": "point",
- "redeem_value": 6,
- "locations": [
- "655da4b5b659e4ea4e5c5009"
], - "vendors": [
- "6925818738b8adf4652965fa"
], - "categories": [
- "691e7bd5b054463687632ff7"
], - "usage": "",
- "createdAt": "2025-12-01T09:26:39.523Z",
- "updatedAt": "2025-12-02T07:37:01.945Z",
- "remaining_count": 3,
- "total": 3,
- "redeemed_count": 3,
- "redeemed_value": 3,
- "expired_code": 0,
- "expired_value": 0,
- "total_value": 3,
- "unused_code": 0,
- "unused_value": 0
}
}| reward_programs_id required | string Reward program ID (MongoDB ObjectId) |
{- "ok": true,
- "msg": "Added to favorites successfully",
- "data": {
- "_id": "66ab12fc9e7dd9d124c8e021",
- "favorites": [
- "65f12ac49e2b1a2345c7d820"
], - "favorite_count": 12
}
}Marks the authenticated user's redeemed reward as used via the loyalty service. Requires Authorization token.
| reward_id required | string Mongo ID of the reward to mark as used |
{- "ok": true,
- "msg": "Reward marked as used successfully.",
- "data": { }
}Retrieve the pending charging sessions of the currently logged-in user.
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}Retrieve EVSEs that are available for reservation at a specific location, date, time, and charging type.
| date required | string <date> Example: date=2026-03-27 Reservation date in YYYY-MM-DD format. |
| time required | string^([01][0-9]|2[0-3]):[0-5][0-9]$ Example: time=14:30 Reservation start time in HH:mm format. |
| location required | string Example: location=655da4b5b659e4ea4e5c5009 Location ID (MongoDB ObjectId). |
| type required | string Example: type=ac EVSE current type. |
{- "ok": true,
- "msg": "ok",
- "data": [
- {
- "_id": "67dd4256d3aaf9a06257c858",
- "code": "TINOCPO",
- "lotNumber": "TinoCPO",
- "floor": "B1",
- "name": "TinoCPO",
- "currentType": "ac",
- "chargeSpeed": 32,
- "costPerKwh": 10,
- "kwhPerHour": 10,
- "priceNormal": 0.55,
- "priceNormalWithGst": 0.55,
- "priceVip": "-",
- "priceVipWithGst": null,
- "priceSubscription": "-",
- "priceSubscriptionWithGst": "-",
- "isVip": false,
- "hardware_status": "unavailable",
- "imgUrl": "",
- "depositAmount": 5,
- "cancelGracePeriod": "90",
- "reservationBlock": "60",
- "enableSubscriptionPlans": [
- "66b78456642444e4b596a9db",
- "6880590c2646dfa4d575a2c1"
], - "subscriptionPriceEnabled": true,
- "access_type": "public",
- "user_actual_charging_price": 0.55,
- "user_actual_charging_price_with_gst": 0.55
}
]
}Stop a specific charging session of the currently logged-in user.
| session_id required | string The ID of the charging session to stop. |
{- "session_id": "665e8f15ebf7d56c133612ab"
}{- "ok": true,
- "msg": "Charging session stopped successfully"
}Retrieve charge sessions based on query parameters. This is an admin/internal endpoint.
| user_id | string Example: user_id=665e8f15ebf7d56c133612ab Filter by user ID (MongoDB ObjectId) |
| charge_point_id | string Example: charge_point_id=665e8f15ebf7d56c133612ab Filter by charge point ID (MongoDB ObjectId) |
| status | string Enum: "charging" "holding" "completed" "noshow" "canceled" Example: status=completed Filter by session status |
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}Retrieve charging sessions for the currently logged-in user with various filtering options.
| chargepoint_id | string Example: chargepoint_id=665e8f15ebf7d56c133612ab Filter by charge point ID (MongoDB ObjectId) |
| location_id | string Example: location_id=665e8f15ebf7d56c133612ab Filter by location ID (MongoDB ObjectId) |
| status | string Enum: "charging" "holding" "completed" "noshow" "canceled" Example: status=completed Filter by session status |
| type | string Enum: "adhoc" "reserved" "queue" Example: type=adhoc Filter by session type |
| from_date | string <date> Example: from_date=2024-01-01 Filter sessions from this date (inclusive, start of day) |
| to_date | string <date> Example: to_date=2024-01-31 Filter sessions until this date (inclusive, end of day) |
| skip | integer Default: 0 Number of records to skip (pagination) |
| limit | integer Default: 0 Example: limit=20 Maximum number of records to return (0 = no limit) |
| page | integer Default: 1 Example: page=1 Page number for pagination |
| per_page | integer Default: 10 Example: per_page=10 Number of records per page for pagination |
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}Retrieve charging sessions for the current user, including related transaction records.
| chargePointId | string Filter by charge point ID |
| type | string Enum: "adhoc" "reserved" Filter by session type |
| page | integer Default: 1 Page number |
| per_page | integer Default: 10 Items per page |
{- "ok": true,
- "data": [
- {
- "_id": "69af9032ce257fabd46cf014",
- "charge_point_name": "TinoCPO Test change",
- "session_started_at": "2026-03-10T03:29:54.432Z",
- "type": "adhoc",
- "location_name": "Jebson & Jessen",
- "status": "completed",
- "total_with_gst": 10.5,
- "Transactions": [
- {
- "transaction_id": "string",
- "User": "string",
- "gst": 9,
- "amount": 1000,
- "current_balance": 97929,
- "new_balance": 96893.5,
- "type": "subscription_payment",
- "status": "Approved",
- "payment_type": "wallet",
- "is_paid": true,
- "remarks": "",
- "promo_code_id": "string",
- "discount_value": 50,
- "total": 950,
- "total_with_gst": 1035.5,
- "subscription_id": "string",
- "createdAt": "2024-07-12T10:12:28.488Z",
- "updatedAt": "2024-07-12T10:12:28.488Z",
- "__v": 0
}
]
}
], - "total": 209,
- "page": 1
}Retrieve queue history for the current user from queueing_charging, including cancelled and missed queue records. Each item can include a mapped ChargeSession when the queue entry has a related charge_session_id.
| location_id | string Example: location_id=696869d231454e612bbdf207 Filter by location ID |
| status | string Enum: "activated" "cancelled" "missed" Example: status=cancelled Filter queue records by queue status |
| from_date | string <date> Example: from_date=2026-04-01 Filter queue records from this date (inclusive, start of day) |
| to_date | string <date> Example: to_date=2026-04-18 Filter queue records until this date (inclusive, end of day) |
| page | integer Default: 1 Example: page=1 Page number for pagination |
| per_page | integer Default: 10 Example: per_page=10 Number of records per page for pagination |
{- "ok": true,
- "total": 46,
- "page": 1,
- "per_page": 20,
- "data": [
- {
- "_id": "69dcb90b14ac228ec59c4d79",
- "user_id": "66337ada513dff7cb0219963",
- "location_id": "696869d231454e612bbdf207",
- "Location": {
- "_id": "696869d231454e612bbdf207",
- "name": "An test Location 1",
- "address": "77 Enterprise Rd, Singapore 629824",
- "city": "Singapore 1",
- "latitude": 1.3483,
- "longitude": 103.6831
}, - "status": "cancelled",
- "join_at": "2026-04-13T09:36:11.084Z",
- "join_from": "mobile",
- "charge_session_id": null,
- "session_started_at": null,
- "user_name": "Tino Staging",
- "user_phone": "65827277157",
- "cancelled_at": "2026-04-13T09:49:21.878Z",
- "cancelled_from": "mobile",
- "missed_at": null,
- "ChargeSession": null
}, - {
- "_id": "69af8e258e328b6d38ebd37e",
- "user_id": "66337ada513dff7cb0219963",
- "location_id": "655da4b5b659e4ea4e5c5009",
- "Location": {
- "_id": "655da4b5b659e4ea4e5c5009",
- "name": "Bishopsgate Residences 36",
- "address": "18 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3334697,
- "longitude": 103.7022473
}, - "status": "activated",
- "join_at": "2026-03-10T03:21:09.251Z",
- "join_from": "mobile",
- "charge_session_id": "69af9032ce257fabd46cf014",
- "session_started_at": "2026-03-10T03:29:54.449Z",
- "user_name": "Tino Staging",
- "user_phone": "827277157",
- "ampeco_session_id": 202578,
- "charger_name": "TinoCPO Test change",
- "cancelled_at": null,
- "cancelled_from": null,
- "missed_at": null,
- "ChargeSession": {
- "_id": "69af9032ce257fabd46cf014",
- "status": "completed",
- "session_started_at": "2026-03-10T03:29:53.808Z",
- "session_stopped_at": "2026-03-10T03:31:18.285Z",
- "total": 10,
- "total_with_gst": 10.9,
- "charging_fee": 10,
- "charging_fee_with_gst": 10.9,
- "Location": {
- "_id": "655da4b5b659e4ea4e5c5009",
- "name": "Bishopsgate Residences 36",
- "address": "18 Enterprise Rd, Singapore 629824",
- "city": "Singapore",
- "latitude": 1.3334697,
- "longitude": 103.7022473
}, - "Transactions": [
- {
- "_id": "69af91835e0800cf485fba39",
- "amount": 10.9,
- "status": "Approved"
}
], - "Evse": {
- "_id": "67dd4256d3aaf9a06257c858",
- "max_a": "32",
- "max_p": "32000",
- "max_v": "400",
- "floor": "B1",
- "name": "TinoCPO",
- "model": "Wallbox Commander2",
- "lot_number": "TinoCPO",
- "access_type": "public"
}
}
}
]
}Retrieve complete charging statistics including historical data, financial breakdown, and usage patterns for the current user in a single API call.
| type | string Default: "week" Enum: "week" "month" "year" Example: type=week Time period for statistics |
{- "ok": true,
- "data": {
- "totalKwh": 0.016,
- "avgKWhPerSession": 0.003,
- "totalKWhChangePercentage": 45.45,
- "avgKWhPerSessionChangePercentage": -51.52,
- "chartData": [
- {
- "period": "Week1",
- "value": 0.01
}, - {
- "period": "Week2",
- "value": 0.02
}, - {
- "period": "Week3",
- "value": 0.03
}, - {
- "period": "Week4",
- "value": 0.04
}
], - "mostUsedStations": [
- {
- "rank": 1,
- "name": "TinoCPO Test change",
- "numberOfSessions": 6,
- "totalKwh": 0.016
}
], - "financialBreakdown": {
- "totalSpent": 65.51,
- "averageCostPerkwh": 4.09,
- "totalIdlingFeeWithGst": 0.11,
- "cossOverFee": 0
}, - "chargingPatterns": {
- "totalSessions": 6,
- "totalDuration": "3h 39min",
- "averageTimeCharging": "0h 36min"
}
}
}Fetches the latest charge point and EVSE state from Ampeco and upserts them locally. Accepts either an Ampeco chargepoint id or a local ChargePoint _id (24-char). Requires Authorization token.
| chargepoint_id required | string Ampeco chargepoint id or ChargePoint _id |
{- "ok": true
}Renders the dashboard HTML table of a charge point's EVSEs and their VIP user lists.
| chargepoint_id required | string ChargePoint _id |
{- "ok": false,
- "msg": "Something went wrong, please contact CS for supporting."
}Enables or disables subscription-based pricing on a charge point and all of its EVSEs.
| chargepoint_id required | string ChargePoint _id |
| status required | string Enum: "true" "false" Whether subscription pricing is enabled |
{- "ok": true,
- "msg": "Invalid ChargePoint ID"
}Checks with Ampeco whether the given EVSE's hardware status is ready (preparing/finishing) to start a charging session. Accepts either a local EVSE _id (24-char) or an Ampeco EVSE id. Requires Authorization token.
| evse_id required | string EVSE _id or Ampeco EVSE id |
{- "ok": true,
- "msg": ""
}Returns the next upcoming (not yet started) reservation for the given EVSE, if any. Requires Authorization token.
| ampeco_evse_id required | string Ampeco EVSE id |
{- "ampeco_evse_id": "string"
}{- "ok": true,
- "msg": "string",
- "data": {
- "reserve_start": "2019-08-24T14:15:22Z",
- "reserve_minutes": 0
}
}Lists upcoming reservations on a given date, filtered by one of EVSE, charge point or location. Requires Authorization token.
| date required | string <date> Date to list reservations for |
| evse_id | string |
| charge_point_id | string |
| location_id | string |
| skip | integer Default: 0 |
| limit | integer Default: 100 |
{- "ok": true,
- "msg": "string",
- "data": [
- {
- "_id": "string",
- "evse_id": "string",
- "charge_point_id": "string",
- "reserve_start": "2019-08-24T14:15:22Z",
- "reserve_minutes": 0
}
]
}Returns the current status of an active charging session, including live energy charged, running price (with GST), charge point / EVSE details and idling fee. Reads the latest state from Ampeco and cached pricing. Requires Authorization token.
| session_id required | string Ampeco session id |
{- "session_id": "string"
}{- "ok": true,
- "msg": "string",
- "data": {
- "session_id": "string",
- "chargepoint": { },
- "started_at": "2019-08-24T14:15:22Z",
- "finished_at": "2019-08-24T14:15:22Z",
- "current_price": 0,
- "current_price_with_gst": 0,
- "total_charging": 0,
- "status": "string",
- "idling_fee": 0,
- "idling_fee_with_gst": 0
}
}Start a charging session on an EVSE for the authenticated user.
Called by the mobile app and by the camera webhook
(services service → POST /v1/camera/webhook), which authenticates as the
matched user and sends started_by: camera_webhook.
This endpoint requires an Authorization token.
All business outcomes are returned with HTTP 200 and an { ok, msg } envelope —
ok: true (with data) only when the session actually starts; every rejection or
failure returns ok: false with a human-readable msg. See the response examples
for every situation the endpoint (and therefore the camera webhook) can receive.
| chargepoint_id | string Ampeco charge point id, or the ChargePoint Mongo |
| network_id | string EVSE network id of the connector to start. |
| started_by | string Enum: "mobile_app" "camera_webhook" Origin of the start request. Defaults to |
{- "chargepoint_id": "84",
- "network_id": "1",
- "started_by": "camera_webhook"
}{- "ok": true,
- "code": "SUCCESS",
- "msg": "ok",
- "data": {
- "session_id": "123456",
- "start_at": "2026-02-12T09:17:40.000Z",
- "session_started_at": "2026-02-12T09:17:40.000Z",
- "success": true
}
}Adds one or more users (matched by phone number) to an EVSE's restricted/VIP access list. Phone numbers are provided newline-separated; matching users are resolved and pushed to the charging service.
| numbers required | string Newline-separated phone numbers |
| id required | string EVSE _id |
{- "numbers": "91234567\n98765432",
- "id": "string"
}{- "ok": true,
- "msg": "VIPs Added"
}Removes a user from an EVSE's restricted/VIP access list and syncs the removal to the charging service.
| vip_id required | string User _id to remove |
| evse_id required | string EVSE _id |
{- "vip_id": "string",
- "evse_id": "string"
}{- "ok": true,
- "msg": "VIP removed from Charger"
}Renders the dashboard HTML page listing the whitelisted (VIP) users allowed to use the given EVSE.
| id required | string EVSE _id |
{- "ok": false,
- "msg": "Something went wrong, please contact CS for supporting."
}Queries Ampeco for the charge point status and reports whether the given EVSE is preparing/finishing (ready to start). Requires Authorization token.
| charge_point_id required | string |
| evse_id required | string |
{- "ok": true,
- "msg": "string"
}Returns enabled locations near the given coordinates with EVSE availability, pricing and subscription-aware rates. Results are cached briefly. Requires Authorization token.
| latitude required | string |
| longitude required | string |
| radius | number Default: 5 |
{- "ok": true,
- "data": {
- "current_address": "string",
- "location": [
- { }
]
}
}Returns detailed info for one location including its EVSEs, availability and subscription-aware pricing. Requires Authorization token.
| location_id required | string |
| latitude | string |
| longitude | string |
{- "ok": true,
- "data": {
- "location": { },
- "evses": [
- { }
], - "countEvses": { }
}
}Resolves an EVSE from a scanned QR short code and returns its location, pricing and reservation status for the logged-in user. Requires Authorization token.
| short_code required | string |
{- "short_code": "string"
}{- "ok": true,
- "msg": "Found Charger",
- "data": { }
}Retrieve EVSEs that are available for reservation at a specific location, date, time, and charging type.
| date required | string <date> Example: date=2026-03-27 Reservation date in YYYY-MM-DD format. |
| time required | string^([01][0-9]|2[0-3]):[0-5][0-9]$ Example: time=14:30 Reservation start time in HH:mm format. |
| location required | string Example: location=655da4b5b659e4ea4e5c5009 Location ID (MongoDB ObjectId). |
| type required | string Example: type=ac EVSE current type. |
{- "ok": true,
- "msg": "ok",
- "data": [
- {
- "_id": "67dd4256d3aaf9a06257c858",
- "code": "TINOCPO",
- "lotNumber": "TinoCPO",
- "floor": "B1",
- "name": "TinoCPO",
- "currentType": "ac",
- "chargeSpeed": 32,
- "costPerKwh": 10,
- "kwhPerHour": 10,
- "priceNormal": 0.55,
- "priceNormalWithGst": 0.55,
- "priceVip": "-",
- "priceVipWithGst": null,
- "priceSubscription": "-",
- "priceSubscriptionWithGst": "-",
- "isVip": false,
- "hardware_status": "unavailable",
- "imgUrl": "",
- "depositAmount": 5,
- "cancelGracePeriod": "90",
- "reservationBlock": "60",
- "enableSubscriptionPlans": [
- "66b78456642444e4b596a9db",
- "6880590c2646dfa4d575a2c1"
], - "subscriptionPriceEnabled": true,
- "access_type": "public",
- "user_actual_charging_price": 0.55,
- "user_actual_charging_price_with_gst": 0.55
}
]
}Cancels a reserved charge session, releasing or capturing the deposit depending on the cancel grace period. Requires Authorization token.
| session_id required | string |
{- "session_id": "string"
}{- "ok": true,
- "msg": "Reservation cancelled"
}Returns EVSEs at a location that can be reserved for the given date/time and current type, excluding already-booked slots. Requires Authorization token.
| date required | string |
| time required | string |
| location required | string |
| type required | string Enum: "ac" "dc" |
{- "ok": true,
- "data": [
- { }
]
}Reserves an EVSE timeslot for the logged-in user after taking a deposit (wallet or card pre-auth) and creating a reserved charge session. Requires Authorization token.
| evse required | string EVSE id |
| date required | string |
| time required | string |
required | object |
{- "evse": "string",
- "date": "string",
- "time": "string",
- "selectedPayment": {
- "methodType": "CC",
- "card": { }
}
}{- "ok": true,
- "msg": "string",
- "data": {
- "reservation_id": "string"
}
}Retrieve charge sessions based on query parameters. This is an admin/internal endpoint.
| user_id | string Example: user_id=665e8f15ebf7d56c133612ab Filter by user ID (MongoDB ObjectId) |
| charge_point_id | string Example: charge_point_id=665e8f15ebf7d56c133612ab Filter by charge point ID (MongoDB ObjectId) |
| status | string Enum: "charging" "holding" "completed" "noshow" "canceled" Example: status=completed Filter by session status |
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}Generate and email a report of charge sessions within a date range. This is an admin endpoint.
| from_date required | string <date> Example: from_date=2024-01-01 Start date for the report |
| to_date required | string <date> Example: to_date=2024-01-31 End date for the report |
| limit | integer Default: 1000 Example: limit=1000 Maximum number of sessions to include |
| skip | integer Default: 0 Number of sessions to skip (pagination) |
{- "ok": true
}Retrieve charging sessions for the currently logged-in user with various filtering options.
| chargepoint_id | string Example: chargepoint_id=665e8f15ebf7d56c133612ab Filter by charge point ID (MongoDB ObjectId) |
| location_id | string Example: location_id=665e8f15ebf7d56c133612ab Filter by location ID (MongoDB ObjectId) |
| status | string Enum: "charging" "holding" "completed" "noshow" "canceled" Example: status=completed Filter by session status |
| type | string Enum: "adhoc" "reserved" "queue" Example: type=adhoc Filter by session type |
| from_date | string <date> Example: from_date=2024-01-01 Filter sessions from this date (inclusive, start of day) |
| to_date | string <date> Example: to_date=2024-01-31 Filter sessions until this date (inclusive, end of day) |
| skip | integer Default: 0 Number of records to skip (pagination) |
| limit | integer Default: 0 Example: limit=20 Maximum number of records to return (0 = no limit) |
| page | integer Default: 1 Example: page=1 Page number for pagination |
| per_page | integer Default: 10 Example: per_page=10 Number of records per page for pagination |
{- "ok": true,
- "data": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}Retrieve charging sessions for the current user, including related transaction records.
| chargePointId | string Filter by charge point ID |
| type | string Enum: "adhoc" "reserved" Filter by session type |
| page | integer Default: 1 Page number |
| per_page | integer Default: 10 Items per page |
{- "ok": true,
- "data": [
- {
- "_id": "69af9032ce257fabd46cf014",
- "charge_point_name": "TinoCPO Test change",
- "session_started_at": "2026-03-10T03:29:54.432Z",
- "type": "adhoc",
- "location_name": "Jebson & Jessen",
- "status": "completed",
- "total_with_gst": 10.5,
- "Transactions": [
- {
- "transaction_id": "string",
- "User": "string",
- "gst": 9,
- "amount": 1000,
- "current_balance": 97929,
- "new_balance": 96893.5,
- "type": "subscription_payment",
- "status": "Approved",
- "payment_type": "wallet",
- "is_paid": true,
- "remarks": "",
- "promo_code_id": "string",
- "discount_value": 50,
- "total": 950,
- "total_with_gst": 1035.5,
- "subscription_id": "string",
- "createdAt": "2024-07-12T10:12:28.488Z",
- "updatedAt": "2024-07-12T10:12:28.488Z",
- "__v": 0
}
]
}
], - "total": 209,
- "page": 1
}Pay a specific charging session of the currently logged-in user.
| session_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the charging session to pay. |
| payment_method | string Payment method to use (e.g., wallet, card) |
| card_id | string Card ID to use if payment_method is card |
{- "payment_method": "wallet",
- "card_id": "card_123456789"
}{- "ok": true,
- "msg": "Make payment successfully.",
- "data": {
- "transactionId": "665e8f15ebf7d56c133612ab"
}
}Retrieve complete charging statistics including historical data, financial breakdown, and usage patterns for the current user in a single API call.
| type | string Default: "week" Enum: "week" "month" "year" Example: type=week Time period for statistics |
{- "ok": true,
- "data": {
- "totalKwh": 0.016,
- "avgKWhPerSession": 0.003,
- "totalKWhChangePercentage": 45.45,
- "avgKWhPerSessionChangePercentage": -51.52,
- "chartData": [
- {
- "period": "Week1",
- "value": 0.01
}, - {
- "period": "Week2",
- "value": 0.02
}, - {
- "period": "Week3",
- "value": 0.03
}, - {
- "period": "Week4",
- "value": 0.04
}
], - "mostUsedStations": [
- {
- "rank": 1,
- "name": "TinoCPO Test change",
- "numberOfSessions": 6,
- "totalKwh": 0.016
}
], - "financialBreakdown": {
- "totalSpent": 65.51,
- "averageCostPerkwh": 4.09,
- "totalIdlingFeeWithGst": 0.11,
- "cossOverFee": 0
}, - "chargingPatterns": {
- "totalSessions": 6,
- "totalDuration": "3h 39min",
- "averageTimeCharging": "0h 36min"
}
}
}Retrieves charge sessions for the authenticated user from the Charging service. The user id is applied automatically; additional query filters are passed through. Requires Authorization token.
| page | integer |
| per_page | integer |
| status | string |
{- "ok": true,
- "data": [
- { }
]
}Returns the logged-in user's active charging session, fee-calculating session, reservation, recent transactions and any broadcast message. Cached briefly. Requires Authorization token.
{- "ok": true,
- "data": {
- "charging": { },
- "fee_calculating": { },
- "recent_transactions": [
- { }
], - "broadcast": { }
}
}Retrieve the transactions of the currently logged-in user.
| month | integer [ 1 .. 12 ] Example: month=1 Month for filtering transactions (1-12) |
| year | integer [ 2000 .. 2100 ] Example: year=2023 Year for filtering transactions (e.g., 2023) |
| from_date | string <date> Example: from_date=2023-01-01 Start date for filtering transactions |
| to_date | string <date> Example: to_date=2023-12-31 End date for filtering transactions |
| status | string Example: status=completed Filter transactions by status (e.g., completed, pending, failed, paid, unpaid) |
| type | string Example: type=charge_session Filter transactions by type (e.g., charge_session) |
| charge_session_id | string Example: charge_session_id=665e8f15ebf7d56c133612ab ID of the charge session to filter transactions (must be a valid ObjectId) |
| page | integer Example: page=1 Page number for pagination |
| per_page | integer Example: per_page=10 Number of items per page for pagination |
{- "ok": true,
- "total": 20,
- "page": 1,
- "data": [
- {
- "transaction_id": "string",
- "User": "string",
- "gst": 9,
- "amount": 1000,
- "current_balance": 97929,
- "new_balance": 96893.5,
- "type": "subscription_payment",
- "status": "Approved",
- "payment_type": "wallet",
- "is_paid": true,
- "remarks": "",
- "promo_code_id": "string",
- "discount_value": 50,
- "total": 950,
- "total_with_gst": 1035.5,
- "subscription_id": "string",
- "createdAt": "2024-07-12T10:12:28.488Z",
- "updatedAt": "2024-07-12T10:12:28.488Z",
- "__v": 0
}
]
}Pay a specific transaction of the currently logged-in user.
| transaction_id required | string Example: 665e8f15ebf7d56c133612ab The ID of the transaction to pay. |
| payment_method | string Payment method to use (e.g., wallet, card) |
| card_id | string Card ID to use if payment_method is card |
{- "payment_method": "wallet",
- "card_id": "card_123456789"
}{- "ok": true,
- "msg": "Transaction paid successfully",
- "card_id": "card_123456789"
}Retrieve the outstanding payments of the currently logged-in user.
{- "ok": true,
- "data": {
- "total_count": 2,
- "total_amount": 50.75,
- "charge_sessions": [
- {
- "_id": "665e8f15ebf7d56c133612ab",
- "ampeco_session_id": "123456",
- "ampeco_chargepoint_id": "84",
- "ampeco_evse_id": "1",
- "User": "665e8f15ebf7d56c133612ab",
- "Evse": "665e8f15ebf7d56c133612ab",
- "ChargePoint": "665e8f15ebf7d56c133612ab",
- "Location": "665e8f15ebf7d56c133612ab",
- "CPO": "665e8f15ebf7d56c133612ab",
- "SeedingPartner": "665e8f15ebf7d56c133612ab",
- "session_base_price": 1000,
- "tariff": 100,
- "price_kwh": 0.5,
- "price_type": "vip",
- "energy": 50,
- "type": "adhoc",
- "status": "completed",
- "session_started_at": "2023-10-01T10:00:00.000Z",
- "session_ended_at": "2023-10-01T11:00:00.000Z",
- "session_stopped_at": "2023-10-01T10:55:00.000Z",
- "fully_charged_at": "2023-10-01T10:45:00.000Z",
- "unplugged_at": "2023-10-01T10:50:00.000Z",
- "total": 250,
- "gst": 7,
- "total_with_gst": 267.5,
- "charging_fee": 200,
- "charging_fee_with_gst": 214
}
]
}
}Returns a list of transactions from the payment service, transformed for the client. Query parameters are passed through to the payment service (pagination, filters). Requires Authorization token.
| page | integer |
| per_page | integer |
| type | string |
{- "ok": true,
- "data": [
- { }
]
}Creates a transaction record from the request body. Requires Authorization token.
| property name* additional property | any |
{ }{- "ok": true,
- "data": "string"
}Returns a detailed payment payload for a transaction. The shape varies by transaction type (subscription_payment, topup, deposit, charging/idle) and merges data from the payment, subscription and charging services.
| transaction_id required | string Transaction ObjectId or external transaction_id |
{- "ok": true,
- "data": { }
}Sends the charge invoice email for the given transaction to the recipient email (defaults to the user's email).
| transaction_id required | string |
string Override recipient email |
{- "ok": true,
- "msg": "Email sent"
}{- "ok": true,
- "msg": "",
- "data": [
- {
- "id": "string",
- "start_at": "2019-08-24T14:15:22Z",
- "end_at": "2019-08-24T14:15:22Z",
- "img_path": "string",
- "title": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Returns active information categories of type "news" (default) or "faq".
| type | string Enum: "news" "faq" Category type to list; defaults to news. |
{- "ok": true,
- "msg": "Ok",
- "data": [
- {
- "category_name": "string",
- "description": "string",
- "id": "string",
- "status": 1,
- "thumbnail_link": "string",
- "type": "string",
- "created_at": "2019-08-24T14:15:22Z"
}
]
}Returns information items for the given category. If the category type is "faq", returns the category's FAQs instead of news items.
| category_id | string Information category ID to fetch the feed for. |
{- "ok": true,
- "msg": "",
- "data": [
- { }
]
}Fetches users from the User service and maps them into the Netsuite customer shape. Supports optional creation-date filtering.
| limit | integer Default: 1000 Max number of customers to return (maps to per_page). |
| created_from | string <date-time> Only include users created on/after this date. |
| created_to | string <date-time> Only include users created on/before this date. |
{- "ok": true,
- "hash": "",
- "data": [
- { }
]
}Fetches a batch of users and asynchronously sends each one to Netsuite. Responds immediately with the count being processed. No-op when Netsuite syncing is disabled.
| per_page | integer Default: 10000 |
| page | integer Default: 1 |
| created_from | string <date-time> |
| created_to | string <date-time> |
string or Array of strings Specific user IDs to send (string or array). | |
| is_guest | boolean |
{- "per_page": 10000,
- "page": 1,
- "created_from": "2019-08-24T14:15:22Z",
- "created_to": "2019-08-24T14:15:22Z",
- "ids": "string",
- "is_guest": true
}{- "ok": true,
- "msg": "Sending 10 customers to Netsuite",
- "data": {
- "number_of_customers": 10
}
}Fetches the user by ID, transforms it into the Netsuite customer shape, and posts it to Netsuite. Records the sync result and marks the user as sent on success. No-op when Netsuite syncing is disabled.
| user_id required | string |
{- "ok": true,
- "Code": 200
}Fetches a transaction, builds the appropriate Netsuite invoice (charging, subscription, deposit, or topup based on type) and posts it to Netsuite. Records the sync result and marks the transaction as sent on success. No-op when Netsuite syncing is disabled.
| transaction_id required | string |
| batchCode | string Optional batch identifier for the sync. |
{- "batchCode": "string"
}{- "invoice": { },
- "response": {
- "Code": 200
}
}Collects Approved transactions (charging, deposit, subscription, topup) matching the filters and asynchronously sends each one to Netsuite under a generated batch code. Responds immediately with the transaction IDs being processed. Requires ids, from_date, or to_date. No-op when Netsuite syncing is disabled.
| from_date | string <date-time> |
| to_date | string <date-time> |
| include_failed_transaction | boolean |
| exclude_charging | boolean |
| exclude_deposit | boolean |
| exclude_subscription | boolean |
| exclude_topup | boolean |
string or Array of strings | |
| page | integer Default: 1 |
| per_page | integer Default: 10 |
{- "from_date": "2019-08-24T14:15:22Z",
- "to_date": "2019-08-24T14:15:22Z",
- "include_failed_transaction": true,
- "exclude_charging": true,
- "exclude_deposit": true,
- "exclude_subscription": true,
- "exclude_topup": true,
- "ids": "string",
- "page": 1,
- "per_page": 10
}{- "ok": true,
- "msg": "Sent 5 invoices to Netsuite",
- "data": {
- "transaction_ids": [
- "string"
]
}
}Utility script that iterates every document in the given collection, uploads the referenced local image files for the specified fields to storage, and updates each document with the new file paths.
| collection_name required | string Name of the Mongoose model/collection to process. |
| field_names required | Array of strings Document fields whose file values should be uploaded to storage. |
{- "field_names": [
- "string"
]
}{- "ok": true,
- "data": [
- { }
]
}Serves a same-origin HTML console (services service →
docs/webhook-test.html) that lets a third-party partner push a signed sample
webhook to their own endpoint during onboarding.
Env-gated behind WEBHOOK_TEST_TOOL_ENABLED=true; returns 404 when disabled.
The page calls POST /v1/webhooks/test/integrate-webhook.
Pushes one signed sample event to a partner-supplied URL so they can verify their integration from their side, and returns the key the sample was signed with.
The delivery is synchronous and is not persisted or retried (unlike real
outbound webhooks). Only sample data is ever sent; the envelope carries
"test": true and the request includes an X-Watt-Test: true header so a partner
never mistakes it for real traffic. Signing matches production exactly:
X-Watt-Signature: t=<unix>,v1=<hmac-sha256 of "t.rawBody">.
The target URL must be public HTTP(S) and must not resolve to a loopback, private, or link-local address (SSRF protection, enforced outside development).
Env-gated behind WEBHOOK_TEST_TOOL_ENABLED=true. When
WEBHOOK_TEST_TOOL_TOKEN is set, callers must send it as an X-Test-Token header.
Rate limited per IP (WEBHOOK_TEST_TOOL_RATE_LIMIT, default 10/min).
See services/docs/partner-webhook-integration.md for the full partner guide.
| X-Test-Token | string Required only when |
| url required | string <uri> Partner endpoint to receive the sample webhook. Public HTTPS. |
| event | string Enum: "session.started" "session.stopped" "session.idling_started" "charger.down" "charger.up" "charger.status" Event type to send. Defaults to |
| secret | string Verify with your own secret. If omitted, a one-off |
{- "event": "session.started",
- "secret": "whsec_test_9a3f..."
}{- "ok": true,
- "msg": "Your endpoint accepted the test webhook.",
- "data": {
- "event": "session.started",
- "secret": "whsec_test_9a3f...",
- "generated_key": true,
- "accepted": true,
- "response_status": 200
}
}Saves a tokenized credit/debit card to the user's account.
Stripe flow: validates the card token against Stripe, attaches to the Stripe customer, saves to TokenizedCard.
2C2P flow: the card is tokenized client-side via 2C2P UI/SDK. The mobile app completes the 0$ tokenization to get an invoiceNo. The app sends the invoiceNo and the server calls 2C2P inquiry to get the customer token and card metadata.
The payment_gateway saved on the card becomes the source of truth for all future payments with that card.
2C2P required params: when
payment_gatewayis"2c2p", the fieldinvoiceNois required.
| card_token | string [Stripe only] Tokenized card identifier from Stripe (e.g. |
| payment_gateway | string Enum: "stripe" "2c2p" Payment gateway. Defaults to |
| is_default | integer Set to |
| invoiceNo | string [2C2P only, required] The invoice number from 2C2P tokenization step. |
{- "payment_gateway": "2c2p",
- "invoiceNo": "b1bcbe740fef41449768",
- "is_default": 1
}{- "ok": true,
- "msg": "Card added successfully"
}