FIZ Invoicing 是做什麼的?
使用 FIZ Public API 開立發票 — REST 閘道位於 https://api.fiz.co。
此 Skill 會引導您完成完整生命週期:尋找或建立客戶、尋找或建立品項、建立草稿發票、開立發票(這是具有法律約束力的步驟),並選擇性地下載 PDF。
設定
每個請求都需在 x-api-key 標頭中帶入用戶端的 API 金鑰。請至 https://app.fiz.co/settings/integrations 取得金鑰。
將其儲存在環境變數中,以免寫死在指令中:
export FIZ_API_KEY="fiz_api_..." # 來自 app.fiz.co 的用戶金鑰
export FIZ_API_URL="https://api.fiz.co" # 選用;此為預設值
以下所有範例皆使用 $FIZ_API_KEY 和 $FIZ_API_URL。若 FIZ_API_URL 未設定,則使用 https://api.fiz.co。若 FIZ_API_KEY 未設定,請停止並告知用戶需在環境中設定(在 shell 中執行 export FIZ_API_KEY=…,或使用密碼管理器)— 請勿要求用戶將金鑰貼入對話中,且絕不列印或顯示金鑰值。API 金鑰是憑證,請勿讓其出現在對話紀錄中。
在 scripts/fiz.sh 中提供了一個可重複使用的 curl 輔助腳本。指令從對話的工作目錄(您的專案根目錄)執行,而非 Skill 目錄,因此請透過 ${CLAUDE_SKILL_DIR} 的絕對路徑來載入輔助腳本(Claude Code 會將此設定為 Skill 本身的目錄):
source "${CLAUDE_SKILL_DIR}/scripts/fiz.sh" # 可從任何工作目錄解析
fiz GET /invoices
在未提供 CLAUDE_SKILL_DIR 的執行環境中,請替換為該環境相對應的 Skill 目錄路徑(單純的相對路徑 scripts/fiz.sh 將無法從專案根目錄解析)。
輔助腳本會印出 HTTP 狀態,並在遇到 4xx/5xx 狀態碼時回傳非零值,因此錯誤回應絕不會被誤認為成功——請參閱下方的「錯誤處理」。文中也內嵌了純 curl 的範例;若使用原始 curl,請務必檢查 HTTP 狀態,而不僅是檢查指令是否以狀態碼 0 結束。
心智模型
- 一張發票會參照一個客戶(以 ID 表示)及一個或多個品項(以 ID 表示)。 因此,客戶和品項必須在建立發票之前就已存在。
POST /invoices會建立一個草稿。草稿尚非法定文件——它不會被傳送至稅務機關,且可以自由編輯或刪除。POST /invoices/:id/issue會開立發票——為其分配正式編號和 ATCUD,與葡萄牙稅務機關 (AT) 同步,並使其成為最終版本。 開立是不可逆的;請在開立前與用戶確認。 已開立的發票無法刪除——唯一撤銷的方式是開立折讓單。- 唯一例外是「先建立後開立」:若在建立
INVOICE_RECEIPT或SIMPLIFIED_INVOICE類型的發票時傳入payment物件,則該文件會記錄付款——但仍需開立才能完成最終程序。
寫入操作前需確認
以下端點會變更用戶帳戶的狀態。需有兩個層級的謹慎處理:
- 先規劃,然後在首次寫入前預覽所有操作。 一旦知道請求所需的內容,請列出您打算為此任務進行的每一次寫入操作——包含每個端點及其 JSON 承載(要建立的客戶、每個品項、草稿發票)——並在一個預覽中向用戶展示這批操作。待用戶批准該計劃後,再依序進行寫入。若計劃在執行過程中發生變化(例如品項查詢失敗,現在需要建立一個),請在發送前預覽新的寫入操作。絕不自行杜撰客戶資料、稅務欄位或金額——僅使用用戶提供給您的內容。
- 在
POST /invoices/:id/issue之前——此操作不可逆,且會向稅務機關申報。請務必取得一次明確、分開的確認(超越上述的計劃批准),向用戶展示草稿的客戶、明細項目、VAT 和總額。切勿自行決定開立。
呼叫政策(審慎考量): 此 Skill 保持模型自動呼叫啟用狀態——description 為探索層面,真正的安全網是上述的「預覽所有寫入」加上「分開確認開立」,而非限制探索。Codex manifest (agents/openai.yaml) 已設定為比對 (allow_implicit_invocation: true)。若操作者希望僅限手動使用,可在 frontmatter 中設定 disable-model-invocation: true(僅在 /fiz-invoicing 路徑下載入)。
這是葡萄牙稅務發票——為何正確性至關重要
FIZ 會開立具有法律約束力的稅務文件,這些文件會申報至葡萄牙稅務機關(Autoridade Tributária,簡稱 AT)。錯誤的 VAT 稅率或遺漏的豁免原因並非簡單的顯示錯誤——它會產生不正確的稅務文件,且一旦開立,只能透過折讓單來更正。請在開立前確保稅務欄位正確。
最可能出錯的兩個事項,您必須仔細考量:
1. VAT 稅率(每個品項的 vatRate)——切勿猜測。 稅率級距(NORMAL|INTERMEDIATE|REDUCED|EXEMPT)及其對應的百分比取決於領土(本土/亞速爾群島/馬德拉群島)。預設為 NORMAL——REDUCED/INTERMEDIATE 僅適用於特定法律定義的類別(特定食品、餐廳、文化活動…)。若用戶未提及此類類別,請使用 NORMAL 並告知用戶,或詢問用戶;切勿在未告知的情況下套用減免稅率。各領土的百分比表請參閱 domain.md。
2. VAT 豁免需要原因代碼(vatExemptionReason)。
若 vatRate 為 EXEMPT,葡萄牙法律要求提供 motivo de isenção——一個說明法律依據的 M 代碼。請務必設定一個;沒有有效原因的豁免品項會導致文件無效,並可能在您開立時被拒絕。該代碼必須反映實際原因:小型企業制度 → M10,性質上豁免的活動(健康/教育)→ M07,歐盟 B2B / 反向徵收 → M40/M16/M19。若用戶符合豁免條件但不知道代碼,請詢問原因並進行對應——切勿任意選擇。完整的代碼清單及法律參考請參閱 domain.md。
其他值得了解的領域規則(詳細內容請見 domain.md):
- CAE 是 5 位數的葡萄牙經濟活動代碼,必須是該企業已登記的其中一個。請勿杜撰——詢問用戶,或從先前的發票中重複使用 CAE。它必須是現行(Rev. 4)代碼。
- NIF(
taxpayerNumber)是 9 位數的葡萄牙稅務編號,包含檢查碼;B2B 交易為必填,最終消費者則為選填。對於歐盟 B2B,客戶的 VAT 號碼對於反向徵收的處理至關重要。 - 源泉扣繳稅款(retenção na fonte:IRS/IRC/IS)是在品項上設定的;自僱服務的常見稅率為 25%。它由付款人扣繳,進而減少實際支付的金額。
- 文件類型會影響規則:
SIMPLIFIED_INVOICE適用於小額零售銷售,可以省略完整的客戶資料;開立給企業且金額超過 €1,000 的INVOICE則需要客戶的 NIF。
工作流程
請遵循以下步驟。如果用戶已提供客戶 ID 和品項 ID,則可跳過步驟 1-2。
步驟 1 — 確認客戶
先搜尋以避免重複,如有需要再建立。
範例使用 fiz 輔助腳本(請參閱設定)——它會為您檢查 HTTP 狀態。等效的原始 curl 請參閱附錄。
依搜尋詞(名稱、稅務編號、電子郵件)尋找:
fiz GET "/customers?search=Joao"
建立客戶(僅 name 為必填):
fiz POST /customers '{
"name": "João Silva",
"email": "[email protected]",
"taxpayerNumber": "303741791",
"country": "PT"
}'
保留回傳的 id——這將是發票的 customerId。
步驟 2 — 確認品項(產品/服務)
尋找現有品項:
fiz GET "/items?search=consulting"
僅在現有品項的稅務欄位與本次銷售相符時,才能重複使用。 找到名稱相符的結果並不夠——對於稅務文件,品項的
vatRate、vatTerritory、vatExemptionReason、taxRate和源泉扣繳欄位必須與您打算對本次客戶和銷售的處理方式相符。如果其中任何一項不同(例如相同的服務,但客戶符合豁免條件、位於其他領土,或需辦理源泉扣繳),請建立一個具有正確欄位的新品項,而非重複使用不匹配的品項。若不確定,請檢查找到的品項欄位並與用戶確認。
建立品項。必填欄位:name、type(PRODUCT|SERVICE)、unitPrice、vatRate(NORMAL|INTERMEDIATE|REDUCED|EXEMPT):
fiz POST /items '{
"name": "Consulting hour",
"type": "SERVICE",
"unitPrice": 80,
"vatRate": "NORMAL"
}'
保留每個回傳的 id——這些將是發票的品項 ID。
unitPrice是單價;每行總額由 FIZ 根據您在發票中提供的quantity計算。請審慎選擇vatRate——請參閱上述領域章節;除非該類別明確適用減免稅率,否則預設為NORMAL。若vatRate為EXEMPT,請務必設定一個與銷售原因相符的vatExemptionReasonM 代碼(例如小型企業制度使用M10)。該欄位在品項建立時技術上為選填,但沒有有效原因的豁免品項是不正確的,稍後在您開立發票時可能會被拒絕。完整的代碼清單請參閱domain.md。
步驟 3 — 建立草稿發票
必填欄位:dueDate(ISO 8601)、cae(葡萄牙經濟活動代碼)、type、customerId,以及 items(至少一個 { id, quantity })。
fiz POST /invoices '{
"dueDate": "2026-07-18T00:00:00.000Z",
"cae": "62010",
"type": "INVOICE",
"customerId": "6863b1513117c5892ff55296",
"items": [
{ "id": "68483e978073231c3947077c", "quantity": 10 }
]
}'
回應中包含新的發票 id(開立時需要)和 status(DRAFT)。發票的 date 會設定為目前時間,currency 則由 API 設定為 EUR——您無需傳送這些欄位。
選用 — 全域折扣(summary):
"summary": { "globalDiscountType": "PERCENT", "globalDiscountPercent": 10 }
若要使用固定金額折扣,請改用 "AMOUNT" 搭配 globalDiscountAmount。
選用 — 建立時付款(payment):僅在 type 為 INVOICE_RECEIPT 或 SIMPLIFIED_INVOICE 時允許;否則 API 會回傳 400。
"payment": { "method": "mbWay", "date": "2026-07-18T00:00:00.000Z" }
method 可為:cash、card、bankTransfer、mbWay、multibanco、spin、other。
步驟 4 — 開立發票
這是具有約束力的步驟。請與用戶確認,然後:
fiz POST /invoices/{id}/issue
回應包含正式編號 number、status: ISSUED 以及 syncWithAt 區塊。請檢查 syncWithAt.status——若為 FAILED,表示發票已在本地建立,但未與稅務機關同步;請向用戶回報 atMessage 及 isRetriable 是否為 true,而非宣稱成功。
步驟 5 — 下載 PDF(選用)
fiz GET /invoices/{id}/pdf
回傳 { id, name, url };url 為 PDF 的可下載連結。
加入 ?format=A4 或 ?format=RECEIPT 以選擇版面配置。
文件類型(type)
值:INVOICE · INVOICE_RECEIPT · SIMPLIFIED_INVOICE · RECEIPT ·
CREDIT_NOTE · DEBIT_NOTE。除非用戶要求收據或簡化發票,否則預設為 INVOICE。僅 INVOICE_RECEIPT 和 SIMPLIFIED_INVOICE 可在建立時接受 payment 物件。各類型的含義及使用時機,請參閱 domain.md。
常用操作參考
| 動作 | 方法與路徑 |
|---|---|
| 列出/搜尋客戶 | GET /customers?search=… |
| 建立客戶 | POST /customers |
| 列出/搜尋品項 | GET /items?search=… |
| 建立品項 | POST /items |
| 建立草稿 | POST /invoices |
| 開立 | POST /invoices/:id/issue |
| 列出發票 | GET /invoices |
| 取得單張發票 | GET /invoices/:id |
| 下載 PDF | GET /invoices/:id/pdf |
| 刪除(草稿) | DELETE /invoices/:id |
錯誤處理
請務必檢查 HTTP 狀態,而不僅是檢查指令是否執行完畢。 發生錯誤時,API 會回傳一個看起來正常的 JSON 主體——{ "statusCode": 400, "message": "...", "timestamp": "..." }——並帶有相符的 HTTP 狀態。使用原始 curl -s 時,該主體會印出,且 curl 仍以狀態碼 0 結束,因此很容易將錯誤誤認為結果。fiz 輔助腳本能防止此情況:它會印出一行 HTTP <code>,並在遇到 4xx/5xx 時回傳非零值。若您必須使用原始 curl,請加上 -w '\n%{http_code}'(或 -o body -w '%{http_code}')並檢查該代碼。
常見狀態:
- 401 — 金鑰遺失或無效。請告知用戶在環境中設定
FIZ_API_KEY(而非在對話中)。 - 400 — 驗證錯誤;
message會說明是哪個欄位。常見情況:空的items、在不支援的type上使用payment、未知或額外的欄位(嚴格的白名單)、格式錯誤的dueDate(必須是完整的 ISO 8601 並含時區,例如2026-07-18T00:00:00.000Z)。 - 5xx — 後端或 AT 問題;請向用戶呈現,不要盲目重試相同的寫入操作(建立操作可能部分成功——請先用
GET檢查)。
請務必將 API 的 message 回報給用戶,而非盲目重試。
完整且權威的請求/回應合約位於即時 Swagger UI:**https://api.fiz.co/**——若此處的欄位看似過時,請查閱該頁面。
需要更多細節時
此 Skill 目錄中有兩個配套檔案:
domain.md— 葡萄牙稅務領域知識:各領土的 VAT 稅率、完整的豁免 (M) 代碼清單及其適用時機、文件類型、CAE/NIF 規則、源泉扣繳稅款,以及 AT 同步/開立不可逆性的運作方式。每當稅務決策不明確時(尤其是選擇vatRate或豁免原因時),請務必閱讀此文件。reference.md— 完整的逐欄位 API 參考(每個客戶/品項/發票欄位、所有列舉值、完整的請求/回應結構)。
附錄 — 原始 curl(不使用輔助腳本)
建議優先使用上述的 fiz 輔助腳本;它會檢查 HTTP 狀態。若無法使用,請使用原始 curl 並加上 -w '\n%{http_code}',然後檢查輸出。