Project

General

Profile

Marketplace » History » Revision 24

Revision 23 (Ryan Supawarapong, 02/20/2026 08:10 AM) → Revision 24/36 (Ryan Supawarapong, 02/20/2026 08:15 AM)

# Marketplace 

 There are the following API: 
 - Get 
 - Sell 
 - Reserve 
 - Update 
   - Confirm 
   - Cancel 
   - Remove 

 ## Diagram 
 <img src="market_place.png"><br> 
 ``` 
 title Market Place 

 actor "customer" as c 
 actor "owner" as o 
 actor "admin" as a 
 participant "frontend" as fe 
 participant "admin" as adm 
 participant "backend" as be 
 database "database" as db 
 participant "notification" as n 

 o->fe: post sell asset 
 fe->be: verify asset and quantities 
 be<->db: query database 
 be->fe: true/false 
 fe->c: true: dispaly new post 
 c->fe: click "interest" button 
 fe->be: update status and count down 15 minutes 
 be<->db: update database 
 be->fe: true/false 
 fe->c: show status "locked" 
 be->n: update payment notification 
 n->c: email bank account info and payment noti within 15 minutes 
 c->n: click confirm payment 
 c->fe: totp to confirm payment 
 fe->be: update payment 
 fe->fe: update status to "pending payment confirm" 
 be<->db: update database 
 be->n: update payment confirmation 
 n->o: email payment acknowledge confirmation and pay service fees 
 o->n: click confirm service fees 
 o->fe: totp to confirm service fees 
 fe->be: update service fees transaction 
 fe->fe: update status to "pending service fees confirm" 
 be<->db: update database 
 be->n: send service fees notification 
 n->a: get noti for new service fees 
 adm<->be: get new service fees 
 a->adm: verify service fees 
 adm<->be: show service fees 
 a->adm: approved service fees 
 adm->be: update service fees status 
 be<->db: update database 
 be->n: send notification 
 n->o: get noti service fees approved 
 fe->fe: update status to "complete" 
 ``` 

 ## API route 

 ## 1) Lists 

 | Type | Value | 
 |---|---| 
 | API Path | `/api/v1/customer/marketplace/lists` | 
 | Request Type | `GET` | 
 | Content-Type | `application/json` | 
 | Authorization | `bearer ...` | 

 ### Request Body 

 | Key | Type | Example | Required | 
 |---|---|---|---| 
 | - | - | - | no body | 

 ### Success Response (200) 

 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"success"` | yes | 
 | data | object | `{"transactions":[...]}` | yes | 
 | data.transactions | array<object> | `[{"id":1,"transactionId":"TXN_123",...}]` | yes | 
 | data.transactions[].id | number | `1` | no (`omitempty`) | 
 | data.transactions[].buyerCode | string | `"90000004"` | no | 
 | data.transactions[].buyerName | string | `"First Last"` | no | 
 | data.transactions[].sellerCode | string | `"90000005"` | no | 
 | data.transactions[].sellerName | string | `"First Last"` | no | 
 | data.transactions[].assetCode | string | `"ASSET001"` | no | 
 | data.transactions[].assetName | string | `"Asset 001"` | no | 
 | data.transactions[].assetShortName | string | `"A001"` | no | 
 | data.transactions[].quantity | number | `10` | no | 
 | data.transactions[].price | number | `10.01` | no | 
 | data.transactions[].totalAmount | number | `100.10` | no | 
 | data.transactions[].transactionId | string | `"TXN_123"` | no | 
 | data.transactions[].currency | string | `"THB"` | no | 
 | data.transactions[].status | number | `1` | no | 
 | data.transactions[].paymentId | string | `"PMT_123"` | no | 
 | data.transactions[].createdAt | string(datetime) | `"2026-02-20T10:00:00Z"` | no | 
 | data.transactions[].deletedAt | object/null | `null` | no | 

 ### Error Response 

 #### Internal Server Error (500) 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"error"` | yes | 
 | message | string | `"database error"` | yes | 

 --- 

 ## 2) Posted 

 | Type | Value | 
 |---|---| 
 | API Path | `/api/v1/customer/marketplace/posted` | 
 | Request Type | `POST` | 
 | Content-Type | `application/json` | 
 | Authorization | `bearer ...` | 

 ### Request Body 

 > `customerCode` and `customerName` are injected from auth token by handler, not required from client body. 

 | Key | Type | Example | Required | 
 |---|---|---|---| 
 | assetCode | string | `"ASSET001"` | yes | 
 | assetName | string | `"Asset 001"` | yes | 
 | assetShortName | string | `"A001"` | yes | 
 | quantity | number | `5` | yes (`> 0`) | 
 | price | number | `10` | yes (`> 0`) | 
 | totalAmount | number | `50` | yes (`> 0`) | 

 ### Success Response (200) 

 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"success"` | yes | 

 ### Error Response 

 #### Bad Request (400) - bind error 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"failed"` | yes | 
 | data | object | `{"error":"...bind error..."}` | yes | 
 | data.error | string | `"code=400, message=..."` | yes | 

 #### Unauthorized (401) - token missing/invalid 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"failed"` | yes | 
 | data | object | `{"error":"invalid token claims"}` | yes | 
 | data.error | string | `"invalid token claims"` | yes | 

 #### Bad Request (400) - validation error 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"failed"` | yes | 
 | data | object | `{"errors":{"assetCode":"required"}}` | yes | 
 | data.errors | object | `{"field":"message"}` | yes | 

 #### Internal Server Error (500) 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"error"` | yes | 
 | message | string | `"internal error"` | yes | 

 --- 

 ## 3) Interested 

 | Type | Value | 
 |---|---| 
 | API Path | `/api/v1/customer/marketplace/interested` | 
 | Request Type | `POST` | 
 | Content-Type | `application/json` | 
 | Authorization | `bearer ...` | 

 ### Request Body 


 | Key | Type | Example | Required | 
 |---|---|---|---| 
 | assetCode | string | `"ASSET001"` | yes | 
 | assetName | string | `"Asset 001"` | yes | 
 | assetShortName | string | `"A001"` | yes | 
 | quantity | number | `5` | yes (`> 0`) | 
 | price | number | `10` | yes (`> 0`) | 
 | totalAmount | number | `50` | yes (`> 0`) | 
 | transactionId | string | `"TXN_123"` | yes | 

 ### Success Response (200) 

 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"success"` | yes | 
 | data | object | `{"emailID":"emailID"}` | yes | 
 | data.emailID | string | `"emailID"` | yes | 

 ### Error Response 

 #### Bad Request (400) - bind error 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"failed"` | yes | 
 | data | object | `{"error":"...bind error..."}` | yes | 
 | data.error | string | `"code=400, message=..."` | yes | 

 #### Unauthorized (401) - token missing/invalid 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"failed"` | yes | 
 | data | object | `{"error":"invalid token claims"}` | yes | 
 | data.error | string | `"invalid token claims"` | yes | 

 #### Bad Request (400) - validation error 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"failed"` | yes | 
 | data | object | `{"errors":{"transactionId":"required"}}` | yes | 
 | data.errors | object | `{"field":"message"}` | yes | 

 #### Internal Server Error (500) 
 | JSON Path | Type | Example | Required | 
 |---|---|---|---| 
 | status | string | `"error"` | yes | 
 | message | string | `"internal error"` | yes |