Community寫作與編輯github.com

FIZ Invoicing

使用 AI 在葡萄牙開立發票 — Claude Code / Agent 適用的 FIZ 發票 API Skill(IVA、豁免、CAE、NIF、AT)

FIZ Invoicing 是什麼?

這個 FIZ Invoicing Skill 提供一個完整的 AI Agent 工作流程,用於透過 FIZ Public API(位於 `https://api.fiz.co`)開立法律上具有約束力的葡萄牙發票。它支援在 Claude Code、Cursor 和支援標準 API 呼叫的平台上使用。該 Skill 引導 Agent 完成整個發票生命週期:尋找或建立客戶與品項、建立草稿、開立發票(即向葡萄牙稅務機關通報的關鍵步驟),以及選擇性地下載 PDF。關鍵的稅務領域知識直接內建,包括 VAT 稅率選擇(預設為 `NORMAL`,除非有明確的減免類別)、VAT 豁免原因代碼(`M` 代碼),以及 CAE 與 NIF 規則,以防止開立不正確的稅務文件。強制執行安全性措施:API 金鑰須透過環境變數設定(絕不寫死或在對話中揭露),並在變更狀態的操作前實施雙階段確認機制——先在草稿建立前預覽所有寫入操作,然後在開立(不可逆)前取得個別的明確確認。此設計能防止意外開立發票或產生不正確的稅務申報。

相容平台✓Claude Code✓Codex CLI~Cursor
npx skills add FIZ-co/fiz-invoicing-skill

Installed? Explore more 寫作與編輯 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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,請務必設定一個與銷售原因相符的 vatExemptionReason M 代碼(例如小型企業制度使用 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
下載 PDFGET /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}',然後檢查輸出。

相關技能