開立發票
開立一張電子發票(F0401),並交給 Turnkey 上傳財政部。
POSThttps://invoice.workat.studio/api/v1/invoices
呼叫成功時,發票已經合法開立、號碼已確定,系統會在背景交給 Turnkey 上傳財政部。上傳結果請用查詢發票的 status 追蹤。
Header
| 名稱 | 值 |
|---|---|
X-Api-Key、X-Timestamp、X-Nonce、X-Signature | 簽章驗證,算法見簽章算法 |
Content-Type | application/json |
Accept | application/json |
請求內容
基本與買方
| 欄位 | 型別 | 說明 | |
|---|---|---|---|
external_id | string ≤ 64 | 選填 | 強烈建議填寫,例如訂單編號。相同的值重送時不會重複開立,見防止重複開立 |
buyer_ban | string,8 碼數字 | 選填 | 買方統一編號。有填就是 B2B 發票(打統編),會檢查統編檢查碼;不填就是 B2C |
buyer_name | string ≤ 60 | 選填 | 買方名稱。B2B 沒填時以統編代替;B2C 沒填時以 4 碼隨機碼作為個人識別碼(財政部規定允許) |
buyer_address | string ≤ 100 | 選填 | 買方地址 |
buyer_email | email ≤ 400 | 選填 | 買方 Email。只保存在本系統,不會上傳財政部 |
載具、捐贈、列印
| 欄位 | 型別 | 說明 | |
|---|---|---|---|
carrier_type | string,6 碼 | 選填 | 載具類別:3J0002 手機條碼、CQ0001 自然人憑證條碼,或公司向財政部申請的會員載具類別號碼 |
carrier_id | string ≤ 400 | 選填 | 載具號碼,必須與 carrier_type 同時提供。手機條碼:/ 開頭共 8 碼、英文須大寫(例 /ABC+123);自然人憑證:2 碼大寫英文 + 14 碼數字。前後不可有空白 |
npoban | string,3–7 碼數字 | 選填 | 捐贈碼(愛心碼)。有填就是捐贈發票 |
print | boolean | 選填 | 是否列印電子發票證明聯。不填時自動判斷:沒有載具也沒有捐贈 → true,否則 false |
課稅與備註
| 欄位 | 型別 | 說明 | |
|---|---|---|---|
tax_type | string | 選填 | 1 應稅(預設)、2 零稅率、3 免稅、9 混稅。同一張發票有應稅與免稅(或零稅率)的品項時用 9,並在每一項明細填 tax_type,見混稅 |
prices_include_tax | boolean | 選填 | 明細的單價、金額是否含稅,預設 true。見下方金額計算 |
zero_tax_rate_reason | string | 條件必填 | 零稅率原因 71–79(營業稅法第 7 條各款)。tax_type 為 2,或混稅發票有零稅率明細時必填 |
customs_clearance_mark | string | 條件必填 | 通關方式:1 非經海關出口、2 經海關出口。tax_type 為 2,或混稅發票有零稅率明細時必填 |
main_remark | string ≤ 200 | 選填 | 發票總備註,會上傳財政部 |
relate_number | string ≤ 20 | 選填 | 相關號碼,會上傳財政部 |
明細 items[]
至少 1 項、最多 9,999 項。
| 欄位 | 型別 | 說明 | |
|---|---|---|---|
description | string ≤ 500 | 必填 | 品名 |
quantity | number > 0 | 必填 | 數量,可有小數(最多 7 位) |
unit_price | number ≥ 0 | 必填 | 單價 |
amount | number ≥ 0 | 選填 | 小計。不填時為 quantity × unit_price;有填時以此為準(例如有折扣時) |
tax_type | string | 條件必填 | 此項的課稅別 1 應稅、2 零稅率、3 免稅。混稅發票(tax_type: "9")每一項都必填;其他發票可省略,有填時必須與發票相同 |
unit | string ≤ 6 | 選填 | 單位,例如「個」「件」 |
remark | string ≤ 120 | 選填 | 單項備註 |
relate_number | string ≤ 50 | 選填 | 單項相關號碼,例如商品條碼 {Z2602970677234} |
載具、捐贈、列印的規則
這三者依財政部規定互相限制,不符合時回應 422:
| 情境 | 載具 | 捐贈 | 列印 | 可以打統編? |
|---|---|---|---|---|
| 存入手機條碼/自然人憑證 | ✅ | — | false | 只有手機條碼可以,見下一列 |
| 打統編+手機條碼(手機條碼報核) | ✅ 限手機條碼 | — | true(必須列印) | ✅ |
| 捐贈 | — | ✅ | false | ❌ 打統編的發票不可捐贈 |
| 列印紙本證明聯 | — | — | true | ✅ |
| ❌ 不合法 | 有載具或捐贈卻要求列印;或沒有載具、沒有捐贈卻指定 print: false(消費者會拿不到發票) | |||
金額計算
系統依財政部規定自動計算,金額四捨五入到整數元:
B2C(沒有 buyer_ban) | B2B(有 buyer_ban) | |
|---|---|---|
| 發票開立方式 | 含稅價 | 未稅金額 + 5% 稅額 |
sales_amount | = 總計 | = round(總計 ÷ 1.05) |
tax_amount | 0 | = 總計 − 銷售額 |
| 明細金額 | 維持原值 | 換算成未稅;換算的尾差調整在最後一項,確保明細合計 = 銷售額 |
範例:B2B 含稅總計 1,000 元 → 銷售額 952、稅額 48。若你的系統提供的是未稅價,請帶 "prices_include_tax": false,系統會改為 未稅 1,000 → 稅額 50、總計 1,050。
混稅
同一張發票同時有應稅與免稅(或零稅率)的品項時,tax_type 填 9,每一項明細各自填 tax_type。
至少要有一項應稅、一項免稅或零稅率。系統依課稅別分組,各組以上表的方式計算後加總:
sales_amount:應稅品項的銷售額(B2C 含稅、B2B 未稅)free_tax_sales_amount/zero_tax_sales_amount:免稅/零稅率品項的合計tax_amount:只有 B2B 的應稅品項有稅額total_amount= 三種銷售額 + 稅額
{
"external_id": "ORDER-20261004-0005",
"tax_type": "9",
"items": [
{ "description": "便當", "quantity": 1, "unit_price": 100, "tax_type": "1" },
{ "description": "雞蛋", "quantity": 1, "unit_price": 60, "tax_type": "3" }
]
}
回應中 sales_amount 為 100、free_tax_sales_amount 為 60、total_amount 為 160。實際哪些品項為免稅請依營業稅法並洽詢國稅局。
範例
以下為請求內容(JSON)。實際送出時需加上簽章 Header,完整程式見PHP 範例或bash 範例。
B2C:存入手機條碼
{
"external_id": "ORDER-20261004-0001",
"carrier_type": "3J0002",
"carrier_id": "/ABC+123",
"items": [
{ "description": "綠茶", "quantity": 10, "unit_price": 25 },
{ "description": "拿鐵", "quantity": 1, "unit_price": 75 }
]
}
B2C:捐贈
{
"external_id": "ORDER-20261004-0002",
"npoban": "8999",
"items": [{ "description": "會員月費", "quantity": 1, "unit_price": 299 }]
}
B2C:列印紙本證明聯
{
"external_id": "ORDER-20261004-0003",
"buyer_name": "王小明",
"items": [{ "description": "商品", "quantity": 2, "unit_price": 150 }]
}
沒有載具也沒有捐贈,print 會自動為 true。
B2B:打統編
{
"external_id": "ORDER-20261004-0004",
"buyer_ban": "22099131",
"buyer_name": "台灣積體電路製造股份有限公司",
"items": [{ "description": "顧問服務費", "quantity": 1, "unit_price": 10500, "unit": "式" }]
}
回應中 sales_amount 為 10000、tax_amount 為 500、total_amount 為 10500。
回應
201 Created 新開立一張發票。200 OK 相同 external_id 已開立過,回傳原本那張。
{
"data": {
"invoice_number": "KZ10000000",
"invoice_date": "2026-10-04",
"invoice_time": "18:35:50",
"random_number": "7887",
"status": "sent",
"external_id": "ORDER-20261004-0001",
"seller_ban": "85426409",
"buyer_ban": null,
"buyer_name": "7887",
"carrier_type": "3J0002",
"carrier_id": "/ABC+123",
"npoban": null,
"print": false,
"tax_type": "1",
"sales_amount": 325,
"zero_tax_sales_amount": 0,
"free_tax_sales_amount": 0,
"tax_amount": 0,
"total_amount": 325,
"items": [
{ "sequence": 1, "description": "綠茶", "quantity": 10, "unit_price": 25, "unit": null, "amount": 250, "tax_type": "1", "remark": null },
{ "sequence": 2, "description": "拿鐵", "quantity": 1, "unit_price": 75, "unit": null, "amount": 75, "tax_type": "1", "remark": null }
]
}
}
回應欄位
| 欄位 | 型別 | 說明 |
|---|---|---|
invoice_number | string | 發票號碼,2 碼英文 + 8 碼數字,例如 KZ10000000 |
invoice_date | string | 開立日期 YYYY-MM-DD(台灣時間) |
invoice_time | string | 開立時間 HH:MM:SS(台灣時間) |
random_number | string | 4 碼防偽隨機碼。消費者查詢發票、列印證明聯時會用到 |
status | string | 開立的上傳進度:issued / sent / uploaded / failed,註銷重開進行中為 cancelling(見發票狀態) |
void | object|null | 未作廢為 null;已作廢時為 {voided_at, reason, remark, approval_number, status, upload_error?},status 為作廢的上傳進度 pending / sent / uploaded / failed(見作廢發票) |
cancellation | object | 只在 status 為 cancelling 時出現:{cancelled_at, reason, status, upload_error},status 為註銷的上傳進度(見註銷重開) |
upload_error | object | 只在 status 為 failed 時出現:{"code": "…", "message": "…"},為 Turnkey 或財政部平台回報的錯誤 |
external_id | string|null | 開立時帶入的冪等鍵 |
seller_ban | string | 賣方統編(即 API 金鑰所屬公司) |
buyer_ban | string|null | 買方統編;B2C 為 null |
buyer_name | string | 買方名稱 |
carrier_type | string|null | 載具類別 |
carrier_id | string|null | 載具號碼 |
npoban | string|null | 捐贈碼;未捐贈為 null |
print | boolean | 是否需要列印電子發票證明聯 |
tax_type | string | 課稅別:1 應稅、2 零稅率、3 免稅、9 混稅 |
sales_amount | integer | 應稅銷售額。B2C 為含稅金額;B2B 為未稅金額;沒有應稅品項為 0 |
zero_tax_sales_amount | integer | 零稅率銷售額 |
free_tax_sales_amount | integer | 免稅銷售額 |
tax_amount | integer | 稅額。B2C 一律為 0 |
total_amount | integer | 總計(消費者實付金額) |
items[] | array | 明細:sequence、description、quantity、unit_price、unit、amount、tax_type、remark。B2B 發票應稅品項的金額為換算後的未稅金額 |
錯誤
| 狀態碼 | 常見原因 |
|---|---|
401/403/429 | 驗證失敗、IP 不在允許清單、請求過於頻繁,見錯誤回應 |
409 | 當期沒有可用的字軌,例如:「統編 85426409 在期別 202609 沒有可用的字軌(發票類別 07),請先匯入字軌或確認號碼是否用完」 |
422 | items:沒有明細、數量為 0、金額為負數、總額為 0 |
items:混稅發票的每一項明細都要指定課稅別;必須同時有應稅與免稅(或零稅率)的明細 | |
items:明細的課稅別與發票不同(請將發票課稅別設為 9) | |
carrier_type:打統編的發票只能搭配手機條碼(手機條碼報核) | |
buyer_ban:買方統一編號檢查碼錯誤 | |
carrier_id:手機條碼格式錯誤:必須是 / 開頭共 8 碼,英文須大寫 | |
carrier_id:載具類別與載具號碼必須同時提供 | |
npoban:捐贈碼必須是 3–7 碼數字 | |
npoban:打統編的發票不可捐贈 | |
print:列印證明聯時不可同時使用載具或捐贈 | |
print:未使用載具也未捐贈時,必須列印證明聯 | |
zero_tax_rate_reason、customs_clearance_mark:零稅率發票必須填寫 |
發生 409、422 時不會消耗發票號碼,修正後可直接重送。