Product
Manage your product catalog with sale and purchase pricing information.
Quick Reference
| Endpoint | Method | Description |
|---|---|---|
/api/v1/products | POST | Create a new product |
/api/v1/products | GET | List all products |
/api/v1/products/:id | GET | Get specific product |
/api/v1/products/:id | PUT | Update product |
/api/v1/products/:id | DELETE | Delete product |
API Endpoints
Create Product
Create a new product with sale and purchase information.
POST /api/v1/products
- cURL
- Go
curl -X POST 'https://api.finan.one/open/api/v1/products' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999' \
-d '{
"general_info": {
"item_name": "Example Product",
"sku_code": "SKU12345",
"unit": "pcs",
"description": "This is a sample product."
},
"sale_info": {
"sale_price": 100000,
"sale_category_code": "C1001",
"sale_tax_code": "TAX_CODE_10"
},
"purchase_info": {
"purchase_price": 80000,
"purchase_category_code": "D1001",
"purchase_tax_code": "TAX_CODE_8"
}
}'
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
type GeneralInfo struct {
ItemName string `json:"item_name"`
SKUCode string `json:"sku_code"`
Unit string `json:"unit,omitempty"`
Description string `json:"description,omitempty"`
}
type SaleInfo struct {
SalePrice int64 `json:"sale_price"`
SaleCategoryCode string `json:"sale_category_code"`
SaleTaxCode string `json:"sale_tax_code,omitempty"`
}
type PurchaseInfo struct {
PurchasePrice int64 `json:"purchase_price"`
PurchaseCategoryCode string `json:"purchase_category_code"`
PurchaseTaxCode string `json:"purchase_tax_code,omitempty"`
}
type CreateProductRequest struct {
GeneralInfo GeneralInfo `json:"general_info"`
SaleInfo SaleInfo `json:"sale_info"`
PurchaseInfo PurchaseInfo `json:"purchase_info"`
}
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 := CreateProductRequest{
GeneralInfo: GeneralInfo{
ItemName: "Example Product",
SKUCode: "SKU12345",
Unit: "pcs",
Description: "This is a sample product.",
},
SaleInfo: SaleInfo{
SalePrice: 100000,
SaleCategoryCode: "C1001",
SaleTaxCode: "TAX_CODE_10",
},
PurchaseInfo: PurchaseInfo{
PurchasePrice: 80000,
PurchaseCategoryCode: "D1001",
PurchaseTaxCode: "TAX_CODE_8",
},
}
jsonBody, _ := json.Marshal(reqBody)
signature := generateSignature(secretKey, "POST", "/api/v1/products", string(jsonBody), timestamp)
req, _ := http.NewRequest("POST", "https://api.finan.one/open/api/v1/products", 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 |
|---|---|---|---|
item_name | string | ✅ | Product name |
sku_code | string | ✅ | Unique SKU code |
unit | string | Unit of measurement (e.g., pcs, kg) | |
description | string | Product description |
sale_info (required)
| Field | Type | Required | Description |
|---|---|---|---|
sale_price | integer | ✅ | Sale price before tax (smallest currency unit) |
sale_category_code | string | ✅ | Income category code. See Code Reference |
sale_tax_code | string | Tax code (e.g., TAX_CODE_10). See Code Reference |
purchase_info (required)
| Field | Type | Required | Description |
|---|---|---|---|
purchase_price | integer | ✅ | Purchase price before tax |
purchase_category_code | string | ✅ | Expense category code. See Code Reference |
purchase_tax_code | string | Tax code. See Code Reference |
Response
- ✅ Success (200)
- ❌ Error
{
"message": { "content": "Thực thi API thành công" },
"code": 102001,
"request_id": "abc123...",
"data": {
"product_id": "PROD-550e8400-e29b-41d4-a716-446655440000",
"general_info": {
"item_name": "Example Product",
"sku_code": "SKU12345",
"unit": "pcs",
"description": "This is a sample product."
},
"sale_info": {
"sale_price": 100000,
"sale_category_code": "C1001",
"sale_tax_code": "TAX_CODE_10"
},
"purchase_info": {
"purchase_price": 80000,
"purchase_category_code": "D1001",
"purchase_tax_code": "TAX_CODE_8"
},
"created_at": "2024-01-20T14:00:00Z"
}
}
| Code | Message | Description |
|---|---|---|
| 400 | Bad Request | Invalid request body |
| 401 | Unauthorized | Invalid authentication |
| 409 | Conflict | SKU code already exists |
| 422 | Unprocessable Entity | Validation failed |
{
"message": {
"content": "Yêu cầu không hợp lệ",
"error": "SKU code SKU12345 already exists"
},
"code": 104000,
"request_id": "abc123..."
}
Get Products
Retrieve all products.
GET /api/v1/products
- cURL
- Go
curl -X GET 'https://api.finan.one/open/api/v1/products' \
-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/products", "", timestamp)
req, _ := http.NewRequest("GET", "https://api.finan.one/open/api/v1/products", 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": [
{
"product_id": "PROD-550e8400-e29b-41d4-a716-446655440000",
"general_info": {
"item_name": "Example Product",
"sku_code": "SKU12345",
"unit": "pcs"
},
"sale_info": {
"sale_price": 100000
},
"purchase_info": {
"purchase_price": 80000
},
"created_at": "2024-01-20T14:00:00Z"
}
]
}
| Code | Message | Description |
|---|---|---|
| 401 | Unauthorized | Invalid authentication |
Get Single Product
GET /api/v1/products/:product_id
Update Product
Replace an existing product's data. This is a full replace — all sections (general_info, sale_info, purchase_info) and their required fields must be included.
PUT /api/v1/products/:product_id
Full Replace
All fields including sale_tax_code and purchase_tax_code are required for update. Omitted fields will be cleared.
- cURL
- Go
curl -X PUT 'https://api.finan.one/open/api/v1/products/PRODUCT_ID' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999' \
-d '{
"general_info": {
"item_name": "Updated Product Name",
"sku_code": "SKU67890",
"unit": "kg",
"description": "Updated description for the product."
},
"sale_info": {
"sale_price": 120000,
"sale_category_code": "C1001",
"sale_tax_code": "TAX_CODE_10"
},
"purchase_info": {
"purchase_price": 100000,
"purchase_category_code": "D1001",
"purchase_tax_code": "TAX_CODE_10"
}
}'
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"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)
productID := "YOUR_PRODUCT_ID"
reqBody := CreateProductRequest{
GeneralInfo: GeneralInfo{
ItemName: "Updated Product Name",
SKUCode: "SKU67890",
Unit: "kg",
Description: "Updated description for the product.",
},
SaleInfo: SaleInfo{
SalePrice: 120000,
SaleCategoryCode: "C1001",
SaleTaxCode: "TAX_CODE_10",
},
PurchaseInfo: PurchaseInfo{
PurchasePrice: 100000,
PurchaseCategoryCode: "D1001",
PurchaseTaxCode: "TAX_CODE_10",
},
}
jsonBody, _ := json.Marshal(reqBody)
path := "/api/v1/products/" + productID
signature := generateSignature(secretKey, "PUT", path, string(jsonBody), timestamp)
url := "https://api.finan.one/open" + path
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": 102001,
"request_id": "abc123...",
"data": {
"product_id": "e5f85e53-d5db-4e4a-8383-61b4cc67398a",
"general_info": {
"item_name": "Updated Product Name",
"sku_code": "SKU67890",
"unit": "kg",
"description": "Updated description for the product."
},
"sale_info": {
"sale_price": 120000,
"sale_category_code": "C1001",
"sale_tax_code": "TAX_CODE_10"
},
"purchase_info": {
"purchase_price": 100000,
"purchase_category_code": "D1001",
"purchase_tax_code": "TAX_CODE_10"
}
}
}
| Code | Message | Description |
|---|---|---|
| 400 | Bad Request | Missing required fields |
| 401 | Unauthorized | Invalid authentication |
| 404 | Not Found | Product not found |
Delete Product
Delete a product from the catalog.
DELETE /api/v1/products/:product_id
- cURL
- Go
curl -X DELETE 'https://api.finan.one/open/api/v1/products/PROD-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)
productID := "PROD-550e8400-e29b-41d4-a716-446655440000"
path := "/api/v1/products/" + productID
signature := generateSignature(secretKey, "DELETE", path, "", timestamp)
url := "https://api.finan.one/open/api/v1/products/" + productID
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 | Product not found |
Next Steps
- Invoice - Create invoices with products
- Customer - Manage customers
- Code Reference - Category and tax codes