Invoice
Create and manage invoices with integrated payment processing.

Quick Referenceβ
| Endpoint | Method | Description |
|---|---|---|
/api/v1/invoices | POST | Create a new invoice |
/api/v1/invoices | GET | List all invoices |
/api/v1/invoices/:id | GET | Get specific invoice |
/api/v1/invoices/:id | PUT | Update invoice |
/api/v1/invoices/:id | DELETE | Delete invoice |
API Endpointsβ
Create Invoiceβ
Create a new invoice with products, customer, and payment methods.
POST /api/v1/invoices
- cURL
- Go
curl -X POST 'https://api.finan.one/open/api/v1/invoices' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999' \
-d '{
"invoice_code": "INV12345",
"transaction_date": "2024-11-22T10:00:00Z",
"due_date": "2024-11-29T10:00:00Z",
"items": [
{
"code": "PRD0001",
"tax_code": "TAX_CODE_10",
"unit_price": 100000,
"quantity": 2,
"note": "note for product"
}
],
"tax_type": "price_excluding_tax",
"discount": {
"is_percentage": false,
"value": 10000
},
"customer": {
"code": "CUST123",
"email": "customer@example.com"
},
"note": "This is a note for the invoice",
"payment_methods": ["bank_transfer", "card", "ewallet_momo"],
"account_id": "54957437-0cb5-4992-ad0e-76d26ba4ddc3"
}'
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
type InvoiceItem struct {
Code string `json:"code"`
TaxCode string `json:"tax_code"`
UnitPrice int64 `json:"unit_price,omitempty"`
Quantity int `json:"quantity"`
Note string `json:"note,omitempty"`
}
type Discount struct {
IsPercentage bool `json:"is_percentage"`
Value float64 `json:"value"`
}
type InvoiceCustomer struct {
Code string `json:"code"`
Email string `json:"email,omitempty"`
}
type CreateInvoiceRequest struct {
InvoiceCode string `json:"invoice_code"`
TransactionDate string `json:"transaction_date"`
DueDate string `json:"due_date"`
Items []InvoiceItem `json:"items"`
TaxType string `json:"tax_type"`
Discount *Discount `json:"discount,omitempty"`
Customer InvoiceCustomer `json:"customer"`
Note string `json:"note,omitempty"`
PaymentMethods []string `json:"payment_methods"`
AccountID string `json:"account_id,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 := CreateInvoiceRequest{
InvoiceCode: "INV12345",
TransactionDate: "2024-11-22T10:00:00Z",
DueDate: "2024-11-29T10:00:00Z",
Items: []InvoiceItem{
{
Code: "PRD0001",
TaxCode: "TAX_CODE_10",
UnitPrice: 100000,
Quantity: 2,
Note: "note for product",
},
},
TaxType: "price_excluding_tax",
Discount: &Discount{
Type: "amount",
Value: 10000,
},
Customer: InvoiceCustomer{
Code: "CUST123",
Email: "customer@example.com",
},
Note: "This is a note for the invoice",
PaymentMethods: []string{"bank_transfer", "card", "ewallet_momo"},
AccountID: "54957437-0cb5-4992-ad0e-76d26ba4ddc3",
}
jsonBody, _ := json.Marshal(reqBody)
signature := generateSignature(secretKey, "POST", "/api/v1/invoices", string(jsonBody), timestamp)
req, _ := http.NewRequest("POST", "https://api.finan.one/open/api/v1/invoices", 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β
| Field | Type | Required | Description |
|---|---|---|---|
invoice_code | string | β | Unique invoice code |
transaction_date | datetime | β | Transaction date (ISO 8601) |
due_date | datetime | β | Payment due date (ISO 8601) |
tax_type | string | β | price_excluding_tax, price_including_tax, or tax_not_applicable |
items | array | β | List of products/services |
customer | object | β | Customer information |
discount | object | Discount configuration | |
note | string | Invoice notes | |
payment_methods | array | β | Accepted payment methods: bank_transfer, card, ewallet_momo |
account_id | uuid | Required for bank_transfer to Shinhan. Get from Account API |
items[]
| Field | Type | Required | Description |
|---|---|---|---|
code | string | β | Product SKU code |
tax_code | string | β | Tax code. See Code Reference |
unit_price | integer | Price per unit (uses product price if empty) | |
quantity | integer | β | Quantity |
note | string | Item note |
discount
| Field | Type | Description |
|---|---|---|
is_percentage | boolean | false for fixed amount, true for percentage |
value | float | Discount value (max 2 decimal places) |
customer
| Field | Type | Required | Description |
|---|---|---|---|
code | string | β | Customer code (must exist in system) |
email | string | Override email for this invoice only |
Responseβ
- β Success (200)
- β Error
{
"message": { "content": "Thα»±c thi API thΓ nh cΓ΄ng" },
"code": 102001,
"request_id": "abc123...",
"data": {
"invoice_id": "INV-550e8400-e29b-41d4-a716-446655440000",
"invoice_code": "INV12345",
"transaction_date": "2024-11-22T10:00:00Z",
"due_date": "2024-11-29T10:00:00Z",
"tax_type": "price_excluding_tax",
"total_amount": 220000,
"total_tax_amount": 20000,
"total_discount_amount": 10000,
"paid_amount": 0,
"unpaid_amount": 220000,
"items": [
{
"code": "PRD0001",
"name": "Product Name",
"quantity": 2,
"unit_price": 100000,
"amount": 200000
}
],
"customer": {
"code": "CUST123",
"name": "Customer Name",
"email": "customer@example.com"
},
"payment_link": "https://book.finan.one/pay/520/invoice/INV12345",
"created_at": "2024-11-22T12:00:00Z"
}
}
| Code | Message | Description |
|---|---|---|
| 400 | Bad Request | Invalid request body |
| 401 | Unauthorized | Invalid authentication |
| 404 | Not Found | Customer or product not found |
| 409 | Conflict | Invoice code already exists |
| 422 | Unprocessable Entity | Validation failed |
{
"message": {
"content": "YΓͺu cαΊ§u khΓ΄ng hợp lα»",
"error": "Customer with code CUST123 not found"
},
"code": 104000,
"request_id": "abc123..."
}
Payment Link
Share the payment_link with your customer for easy payment. Supports all configured payment methods.
Get Invoicesβ
Retrieve all invoices.
GET /api/v1/invoices
- cURL
- Go
curl -X GET 'https://api.finan.one/open/api/v1/invoices' \
-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/invoices", "", timestamp)
req, _ := http.NewRequest("GET", "https://api.finan.one/open/api/v1/invoices", 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": [
{
"invoice_id": "INV-550e8400-e29b-41d4-a716-446655440000",
"invoice_code": "INV12345",
"transaction_date": "2024-11-22T10:00:00Z",
"due_date": "2024-11-29T10:00:00Z",
"total_amount": 220000,
"paid_amount": 220000,
"unpaid_amount": 0,
"payment_link": "https://book.finan.one/pay/520/invoice/INV12345",
"created_at": "2024-11-22T12:00:00Z"
}
]
}
| Code | Message | Description |
|---|---|---|
| 401 | Unauthorized | Invalid authentication |
Get Single Invoice
GET /api/v1/invoices/:invoice_id
Get Payment Requests for Invoiceβ
To retrieve payment requests for an invoice, use the Payment API with filters:
curl -X GET 'https://api.finan.one/open/api/v1/payments?reference_type=invoice&reference_id=INV-550e8400' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999'
Update Invoiceβ
Update an existing invoice with new items, discount, due date, or customer email.
PUT /api/v1/invoices/:invoice_id
- cURL
- Go
curl -X PUT 'https://api.finan.one/open/api/v1/invoices/INVOICE_ID' \
-H 'Content-Type: application/json' \
-H 'x-client-id: YOUR_CLIENT_ID' \
-H 'x-signature: YOUR_SIGNATURE' \
-H 'x-timestamp: 1699999999' \
-d '{
"due_date": "2024-11-29T10:00:00Z",
"items": [
{
"code": "PRD0001",
"tax_code": "TAX_CODE_10",
"unit_price": 100000,
"quantity": 2,
"note": "note for product"
}
],
"discount": {
"is_percentage": false,
"value": 120000
},
"customer": {
"email": "customer@example.com"
},
"note": "This is note of invoice"
}'
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
type UpdateInvoiceItem struct {
Code string `json:"code"`
TaxCode string `json:"tax_code"`
UnitPrice int64 `json:"unit_price,omitempty"`
Quantity int `json:"quantity"`
}
type Discount struct {
IsPercentage bool `json:"is_percentage"`
Value float64 `json:"value"`
}
type UpdateCustomer struct {
Email string `json:"email,omitempty"`
}
type UpdateInvoiceRequest struct {
DueDate string `json:"due_date,omitempty"`
Items []UpdateInvoiceItem `json:"items,omitempty"`
Discount *Discount `json:"discount,omitempty"`
Customer *UpdateCustomer `json:"customer,omitempty"`
Note string `json:"note,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)
invoiceID := "INV-550e8400-e29b-41d4-a716-446655440000"
reqBody := UpdateInvoiceRequest{
DueDate: "2024-12-05T10:00:00Z",
Items: []UpdateInvoiceItem{
{
Code: "PRD0001",
TaxCode: "TAX_CODE_10",
UnitPrice: 100000,
Quantity: 3,
},
},
Note: "Updated invoice note",
}
jsonBody, _ := json.Marshal(reqBody)
path := "/api/v1/invoices/" + invoiceID
signature := generateSignature(secretKey, "PUT", path, string(jsonBody), timestamp)
url := "https://api.finan.one/open/api/v1/invoices/" + invoiceID
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))
}
Updatable Fieldsβ
| Field | Type | Description |
|---|---|---|
due_date | datetime | Updated due date |
items | array | Updated item list |
discount | object | Updated discount |
customer.email | string | Override customer email |
note | string | Invoice notes |
Responseβ
- β Success (200)
- β Error
{
"message": { "content": "Thα»±c thi API thΓ nh cΓ΄ng" },
"code": 102000,
"request_id": "abc123...",
"data": {
"invoice_id": "INV-550e8400-e29b-41d4-a716-446655440000",
"invoice_code": "INV12345",
"due_date": "2024-12-05T10:00:00Z",
"total_amount": 330000,
"updated_at": "2024-11-23T10:00:00Z"
}
}
| Code | Message | Description |
|---|---|---|
| 401 | Unauthorized | Invalid authentication |
| 404 | Not Found | Invoice not found |
| 422 | Unprocessable Entity | Validation failed |
Delete Invoiceβ
Delete an invoice.
DELETE /api/v1/invoices/:invoice_id
- cURL
- Go
curl -X DELETE 'https://api.finan.one/open/api/v1/invoices/INV-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)
invoiceID := "INV-550e8400-e29b-41d4-a716-446655440000"
path := "/api/v1/invoices/" + invoiceID
signature := generateSignature(secretKey, "DELETE", path, "", timestamp)
url := "https://api.finan.one/open/api/v1/invoices/" + invoiceID
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 | Invoice not found |
Payment Requests
If the invoice has payment requests, they remain active after deletion. You can still query payments using reference_type=invoice and reference_id.