Customer
Manage customer records including contact information, addresses, and bank accounts.
Quick Reference
| Endpoint | Method | Description |
|---|---|---|
/api/v1/customers | POST | Create a new customer |
/api/v1/customers | GET | List all customers |
/api/v1/customers/:id | GET | Get specific customer |
/api/v1/customers/:id | PUT | Update customer |
/api/v1/customers/:id | DELETE | Delete customer |
API Endpoints
Create Customer
Create a new customer record.
POST /api/v1/customers
- cURL
- Go
curl -X POST 'https://api.finan.one/open/api/v1/customers' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999' \
-d '{
"general_info": {
"name": "Nguyen Van B",
"customer_code": "CUST20231122",
"phone": "0933456789",
"phone_code": "+84",
"email": "customerb@example.com",
"type": "personal",
"tax_id": "123456789",
"contact_persons": [
{
"name": "Jane Smith",
"phone_number": "987654321",
"email": "jane.smith@example.com"
}
],
"custom_tag": "VIP"
},
"address": {
"country": "Vietnam",
"province": "Ho Chi Minh",
"district": "District 1",
"ward": "Ben Thanh Ward",
"address": "123 Le Loi Street",
"zip_code": "100000"
},
"bank_accounts": [
{
"bank_code": "201",
"bank_name": "Vietcombank",
"account_holder_name": "Nguyen Van B",
"account_number": "123456789012"
}
]
}'
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
type ContactPerson struct {
Name string `json:"name"`
PhoneNumber string `json:"phone_number"`
Email string `json:"email"`
}
type GeneralInfo struct {
Name string `json:"name"`
CustomerCode string `json:"customer_code"`
Phone string `json:"phone"`
PhoneCode string `json:"phone_code"`
Email string `json:"email,omitempty"`
Type string `json:"type"`
TaxID string `json:"tax_id,omitempty"`
ContactPersons []ContactPerson `json:"contact_persons,omitempty"`
CustomTag string `json:"custom_tag,omitempty"`
}
type Address struct {
Country string `json:"country,omitempty"`
Province string `json:"province,omitempty"`
District string `json:"district,omitempty"`
Ward string `json:"ward,omitempty"`
Address string `json:"address,omitempty"`
ZipCode string `json:"zip_code,omitempty"`
}
type BankAccount struct {
BankCode string `json:"bank_code"`
BankName string `json:"bank_name"`
AccountHolderName string `json:"account_holder_name"`
AccountNumber string `json:"account_number"`
}
type CreateCustomerRequest struct {
GeneralInfo GeneralInfo `json:"general_info"`
Address *Address `json:"address,omitempty"`
BankAccounts []BankAccount `json:"bank_accounts,omitempty"`
}
func generateSignature(secretKey, method, path, payload, timestamp string) string {
message := secretKey + "_" + method + "_" + path + "_" + payload + "_" + timestamp
hash := sha256.Sum256([]byte(message))
return hex.EncodeToString(hash[:])
}
func main() {
clientID := "YOUR_CLIENT_ID"
secretKey := "YOUR_SECRET_KEY"
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
reqBody := CreateCustomerRequest{
GeneralInfo: GeneralInfo{
Name: "Nguyen Van B",
CustomerCode: "CUST20231122",
Phone: "0933456789",
PhoneCode: "+84",
Email: "customerb@example.com",
Type: "personal",
TaxID: "123456789",
CustomTag: "VIP",
},
Address: &Address{
Country: "Vietnam",
Province: "Ho Chi Minh",
District: "District 1",
Ward: "Ben Thanh Ward",
Address: "123 Le Loi Street",
ZipCode: "100000",
},
BankAccounts: []BankAccount{
{
BankCode: "201",
BankName: "Vietcombank",
AccountHolderName: "Nguyen Van B",
AccountNumber: "123456789012",
},
},
}
jsonBody, _ := json.Marshal(reqBody)
signature := generateSignature(secretKey, "POST", "/api/v1/customers", string(jsonBody), timestamp)
req, _ := http.NewRequest("POST", "https://api.finan.one/open/api/v1/customers", bytes.NewBuffer(jsonBody))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-client-id", clientID)
req.Header.Set("x-signature", signature)
req.Header.Set("x-timestamp", timestamp)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
Request Body
general_info (required)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Customer full name |
customer_code | string | ✅ | Unique customer identifier |
phone | string | ✅ | Phone number |
phone_code | string | ✅ | International dialing code (e.g., +84) |
email | string | Email address | |
type | string | ✅ | personal or company |
tax_id | string | Tax identification number | |
contact_persons | array | Contact persons (required for company type) | |
custom_tag | string | Custom label (e.g., VIP) |
contact_persons (required for company type)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Contact person name |
phone_number | string | ✅ | Contact phone |
email | string | ✅ | Contact email |
address (optional)
| Field | Type | Description |
|---|---|---|
country | string | Country |
province | string | Province/State |
district | string | District |
ward | string | Ward |
address | string | Street address |
zip_code | string | Postal code |
bank_accounts (optional)
| Field | Type | Description |
|---|---|---|
bank_code | string | Bank code. See Code Reference |
bank_name | string | Bank name |
account_holder_name | string | Account holder name |
account_number | string | Account number |
Response
- ✅ Success (200)
- ❌ Error
{
"message": { "content": "Thực thi API thành công" },
"code": 102001,
"request_id": "abc123...",
"data": {
"customer_id": "550e8400-e29b-41d4-a716-446655440000",
"general_info": {
"name": "Nguyen Van B",
"customer_code": "CUST20231122",
"phone": "0933456789",
"email": "customerb@example.com",
"type": "personal"
},
"address": {
"country": "Vietnam",
"province": "Ho Chi Minh",
"district": "District 1"
},
"bank_accounts": [
{
"bank_code": "201",
"bank_name": "Vietcombank",
"account_number": "123456789012"
}
],
"created_at": "2024-01-20T14:00:00Z"
}
}
| Code | Message | Description |
|---|---|---|
| 400 | Bad Request | Invalid request body |
| 401 | Unauthorized | Invalid authentication |
| 409 | Conflict | Customer code already exists |
| 422 | Unprocessable Entity | Validation failed |
{
"message": {
"content": "Yêu cầu không hợp lệ",
"error": "Customer code already exists"
},
"code": 104000,
"request_id": "abc123..."
}
tip
Ensure customer_code is unique within your system to prevent duplicate records.
Get Customers
Retrieve all customers.
GET /api/v1/customers
- cURL
- Go
curl -X GET 'https://api.finan.one/open/api/v1/customers' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999'
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
func generateSignature(secretKey, method, path, payload, timestamp string) string {
message := secretKey + "_" + method + "_" + path + "_" + payload + "_" + timestamp
hash := sha256.Sum256([]byte(message))
return hex.EncodeToString(hash[:])
}
func main() {
clientID := "YOUR_CLIENT_ID"
secretKey := "YOUR_SECRET_KEY"
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
signature := generateSignature(secretKey, "GET", "/api/v1/customers", "", timestamp)
req, _ := http.NewRequest("GET", "https://api.finan.one/open/api/v1/customers", nil)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-client-id", clientID)
req.Header.Set("x-signature", signature)
req.Header.Set("x-timestamp", timestamp)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
Response
- ✅ Success (200)
- ❌ Error
{
"message": { "content": "Thực thi API thành công" },
"code": 102000,
"request_id": "abc123...",
"data": [
{
"customer_id": "550e8400-e29b-41d4-a716-446655440000",
"general_info": {
"name": "Nguyen Van B",
"customer_code": "CUST20231122",
"type": "personal"
},
"created_at": "2024-01-20T14:00:00Z"
}
]
}
| Code | Message | Description |
|---|---|---|
| 401 | Unauthorized | Invalid authentication |
Get Single Customer
GET /api/v1/customers/:customer_id
Update Customer
Replace an existing customer's data. This is a full replace operation — all required fields must be included, and omitted optional fields will be cleared.
PUT /api/v1/customers/:customer_id
Full Replace, Not Partial Update
You must include general_info.type and all fields you want to keep. Fields not included (e.g., address, bank_accounts) will be reset to empty.
- cURL
- Go
curl -X PUT 'https://api.finan.one/open/api/v1/customers/550e8400-e29b-41d4-a716-446655440000' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999' \
-d '{
"general_info": {
"name": "Updated Customer Name",
"customer_code": "CUST20231122",
"phone": "0933456789",
"phone_code": "+84",
"email": "updated_email@example.com",
"type": "personal",
"custom_tag": "Priority Customer"
},
"address": {
"country": "Vietnam",
"province": "Ho Chi Minh"
}
}'
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
type UpdateCustomerRequest struct {
GeneralInfo map[string]interface{} `json:"general_info,omitempty"`
Address map[string]interface{} `json:"address,omitempty"`
}
func generateSignature(secretKey, method, path, payload, timestamp string) string {
message := secretKey + "_" + method + "_" + path + "_" + payload + "_" + timestamp
hash := sha256.Sum256([]byte(message))
return hex.EncodeToString(hash[:])
}
func main() {
clientID := "YOUR_CLIENT_ID"
secretKey := "YOUR_SECRET_KEY"
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
customerID := "550e8400-e29b-41d4-a716-446655440000"
reqBody := UpdateCustomerRequest{
GeneralInfo: map[string]interface{}{
"name": "Updated Customer Name",
"email": "updated_email@example.com",
"custom_tag": "Priority Customer",
},
}
jsonBody, _ := json.Marshal(reqBody)
path := "/api/v1/customers/" + customerID
signature := generateSignature(secretKey, "PUT", path, string(jsonBody), timestamp)
url := "https://api.finan.one/open/api/v1/customers/" + customerID
req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(jsonBody))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-client-id", clientID)
req.Header.Set("x-signature", signature)
req.Header.Set("x-timestamp", timestamp)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
Response
- ✅ Success (200)
- ❌ Error
{
"message": { "content": "Thực thi API thành công" },
"code": 102000,
"request_id": "abc123...",
"data": {
"customer_id": "550e8400-e29b-41d4-a716-446655440000",
"general_info": {
"name": "Updated Customer Name",
"email": "updated_email@example.com"
},
"updated_at": "2024-01-21T10:00:00Z"
}
}
| Code | Message | Description |
|---|---|---|
| 401 | Unauthorized | Invalid authentication |
| 404 | Not Found | Customer not found |
| 422 | Unprocessable Entity | Validation failed |
Delete Customer
Delete a customer record.
DELETE /api/v1/customers/:customer_id
- cURL
- Go
curl -X DELETE 'https://api.finan.one/open/api/v1/customers/550e8400-e29b-41d4-a716-446655440000' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999'
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
func generateSignature(secretKey, method, path, payload, timestamp string) string {
message := secretKey + "_" + method + "_" + path + "_" + payload + "_" + timestamp
hash := sha256.Sum256([]byte(message))
return hex.EncodeToString(hash[:])
}
func main() {
clientID := "YOUR_CLIENT_ID"
secretKey := "YOUR_SECRET_KEY"
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
customerID := "550e8400-e29b-41d4-a716-446655440000"
path := "/api/v1/customers/" + customerID
signature := generateSignature(secretKey, "DELETE", path, "", timestamp)
url := "https://api.finan.one/open/api/v1/customers/" + customerID
req, _ := http.NewRequest("DELETE", url, nil)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-client-id", clientID)
req.Header.Set("x-signature", signature)
req.Header.Set("x-timestamp", timestamp)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
Response
- ✅ Success (200)
- ❌ Error
{
"message": { "content": "Thực thi API thành công" },
"code": 102001,
"request_id": "abc123...",
"data": "success"
}
| Code | Message | Description |
|---|---|---|
| 401 | Unauthorized | Invalid authentication |
| 404 | Not Found | Customer not found |
| 409 | Conflict | Customer has active invoices |
Dependencies
Deletion may fail if the customer has pending invoices or active contracts. Resolve dependencies first.
Next Steps
- Product - Manage product catalog
- Invoice - Create invoices for customers
- Code Reference - Bank codes