> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluz.app/llms.txt
> Use this file to discover all available pages before exploring further.

# 您的第一筆虛擬卡消費

> 端到端跑一次完整的順利流程 — 挑選卡片方案、以正確設定發卡、揭露卡片、並追蹤其消費 — 全程於沙盒環境中。

本快速入門將帶你從全新的 Fluz 帳戶走到成功發出並可用的虛擬卡。你將註冊應用程式、鑄造具範圍的存取權杖，接著瀏覽卡片方案，依你的使用情境建立並設定卡片、揭露卡片細節，並觀察其交易 — 全都在沙盒環境中，無任何真實金流發生。

<Info>
  **先決條件**

  * 一個 **Fluz 帳戶** — 你將在下方步驟 1–2 建立階段 API 憑證並鑄造存取權杖。
  * 請將請求送往 **沙盒** GraphQL 端點。此處不會對真實卡片請款 — 參見 [Staging vs. Live Environment](/concepts/environments)。
  * 每個 mutation 都需要唯一的 `idempotencyKey`（用戶端產生的 UUID），以確保請求只會被處理一次 — 參見 [Idempotency](/concepts/idempotency)。
</Info>

## 開始之前

除了鑄造你的權杖（步驟 2）之外，每個呼叫都是送至單一 GraphQL 端點的 `POST` 請求，並以你的 bearer 權杖進行驗證：

<CodeGroup>
  ```bash Endpoint & headers theme={null}
  POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql

  Authorization: Bearer <YOUR_USER_ACCESS_TOKEN>
  Content-Type: application/json
  ```

  ```bash Example request (cURL) theme={null}
  curl -X POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql \
    -H "Authorization: Bearer <YOUR_USER_ACCESS_TOKEN>" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "query GetVirtualCardOffers { getVirtualCardOffers { offerId programName rewardValue } }"
    }'
  ```
</CodeGroup>

<Tip>
  Staging 隨附可直接發卡的 **測試卡片方案**，你的沙盒帳戶也包含預先加入、可作為資金來源的測試銀行卡。完整沙盒資料集請見 [Test Merchants](/test-merchants) 與 [Test Bank Cards](/test-bank-cards)。
</Tip>

## 完整流程

<Steps>
  <Step title="註冊並登記應用程式" icon="user-plus">
    於 [fluz.app](https://fluz.app) 建立 Fluz 帳戶，接著開啟 [Developer Console](https://uni.staging.fluzapp.com/developers) 並建立新的 **Staging** 應用程式。當憑證顯示時，請複製你的 `clientId` 與 `clientSecret` —— secret 只會顯示一次。

    完整教學： [Prepare your accounts](/get-started/prepare-accounts)。
  </Step>

  <Step title="以憑證交換存取權杖" icon="key">
    從你的應用程式憑證鑄造短期、具範圍的使用者存取權杖。此呼叫會送至 OAuth 服務；後續所有呼叫都使用回傳的權杖作為 Bearer 憑證。

    <CodeGroup>
      ```bash Mint token (cURL) theme={null}
          curl -X POST https://oauth-service.fluzapp.com/graphql \
            -H "Content-Type: application/json" \
            -d '{
              "query": "mutation ($clientId: String!, $clientSecret: String!, $scopes: [Scope!]!) { generateUserAccessToken(clientId: $clientId, clientSecret: $clientSecret, scopes: $scopes) { accessToken expiresIn scopes } }",
              "variables": {
                "clientId": "<APPLICATION_CLIENT_ID>",
                "clientSecret": "<APPLICATION_CLIENT_SECRET>",
                "scopes": ["MANAGE_PAYMENT", "CREATE_VIRTUALCARD", "EDIT_VIRTUALCARD", "REVEAL_VIRTUALCARD", "PCI_COMPLIANCE"]
              }
            }'
      ```

      ```json Response theme={null}
          {
            "data": {
              "generateUserAccessToken": {
                "accessToken": "eyJhbGciOi...",
                "expiresIn": 3600,
                "scopes": ["MANAGE_PAYMENT", "CREATE_VIRTUALCARD", "EDIT_VIRTUALCARD", "REVEAL_VIRTUALCARD", "PCI_COMPLIANCE"]
              }
            }
          }
      ```
    </CodeGroup>

    儲存回傳的 `accessToken`，並在下方每個請求以 `Authorization: Bearer <accessToken>` 夾帶。權杖為短期有效（`expiresIn` 以秒為單位）—— 請在伺服器端鑄造並於到期前更新。完整細節： [API credentials](/get-started/api-credentials)。

    <Tip>
      Scope 會限定權杖的能力 — 僅包含你的流程所需：`MANAGE_PAYMENT` 用於為你的餘額加值、`CREATE_VIRTUALCARD` 用於瀏覽方案與發卡、`REVEAL_VIRTUALCARD` + `PCI_COMPLIANCE` 用於揭露卡片與拉取其交易、`EDIT_VIRTUALCARD` 用於日後鎖卡、解鎖或編輯卡片。
    </Tip>

    <Warning>
      絕勿在瀏覽器或行動端用戶端暴露 `clientSecret`。請在伺服器端鑄造權杖，並只轉發該權杖。
    </Warning>
  </Step>

  <Step title="為你的 Fluz 餘額加值" icon="wallet">
    當虛擬卡被使用時，會從你的帳戶撥款 — 預設來自你的 **Fluz 餘額**（`FLUZ_BALANCE`）。請確保可用餘額足以涵蓋你計畫設定的消費上限。你可用兩種方式加值：

    * **手動**，透過 [sandbox Fluz website](https://uni.staging.fluzapp.com/manage-money)。
    * **程式化**，透過 `depositCashBalance` mutation。

    <Accordion title="透過 API 加值（depositCashBalance）" icon="banknote-arrow-down">
      先以 `getWallet` 取得資金來源 ID，接著進行存入：

      ```graphql theme={null}
            mutation depositCashBalance($input: DepositCashBalanceInput!) {
              depositCashBalance(input: $input) {
                balances {
                  cashBalance { availableBalance totalBalance pendingBalance }
                }
              }
            }
      ```

      ```json theme={null}
            {
              "input": {
                "idempotencyKey": "0284be6f-1a69-44f7-9da0-5b5edaf45d19",
                "amount": 200.00,
                "depositType": "CASH_BALANCE",
                "bankCardId": "<YOUR_TEST_BANK_CARD_ID>"
              }
            }
      ```

      [gift card Quickstart](/quickstart) 有更完整的步驟說明，包括如何用 `getWallet` 取得付款方式 ID。
    </Accordion>

    <Note>
      想改用已連結的銀行帳戶為卡片撥款嗎？請在發卡（步驟 5）時設定 `primaryFundingSource: BANK_ACCOUNT` 並傳入 `bankAccountId` —— 無需預先加值餘額。
    </Note>
  </Step>

  <Step title="瀏覽卡片方案並選擇一個 offer" icon="layers">
    每張虛擬卡都會對應到一個 **卡片方案**（一個「offer」）：方案決定網路、發卡銀行、回饋比例，以及你的卡片必須遵守的消費上限。使用 `getVirtualCardOffers` 取得你的帳戶可用的方案。

    <CodeGroup>
      ```graphql Query theme={null}
          query GetVirtualCardOffers {
            getVirtualCardOffers {
              offerId
              programName
              bin
              bankName
              rewardValue
              programLimits {
                dailyLimit
                weeklyLimit
                monthlyLimit
              }
            }
          }
      ```

      ```json Response theme={null}
          {
            "data": {
              "getVirtualCardOffers": [
                {
                  "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                  "programName": "Virtual Card",
                  "bin": "543210",
                  "bankName": "Bank of Examples",
                  "rewardValue": "1.5%",
                  "programLimits": {
                    "dailyLimit": "500.00",
                    "weeklyLimit": "2000.00",
                    "monthlyLimit": "5000.00"
                  }
                }
              ]
            }
          }
      ```
    </CodeGroup>

    Offers 會依 `rewardValue` 排序，因此最高回饋的方案會先出現。你也可用選擇性的 `input` 做過濾 — `cardType`（`DEBIT` / `PREPAID`）、`cardNetwork`（`MASTERCARD` / `VISA`）、以及 `cardBrandLocked`。完整參考： [Get Virtual Card Offers](/features/get-card-offers)。

    在沙盒中，以下測試方案皆可使用：

    | Offer ID                               | Program Name                                   | Reward Value |
    | -------------------------------------- | ---------------------------------------------- | ------------ |
    | `ed669305-5e43-40a0-9a25-7a15ed174628` | Virtual Card                                   | 1.5%         |
    | `b23630f6-8d91-43df-84aa-a541e7691197` | Virtual Card - Mastercard Prepaid              | 1.5%         |
    | `592c394e-26cc-44ac-a145-a5f81301fe77` | Brand Locked Virtual Card - Mastercard Prepaid | 1.5%         |

    <Info>
      請保存你選擇的 `offerId` 並留意其 `programLimits` —— 你在下一步設定的 `spendLimit` 必須落在該方案針對你選擇之期間的上限內。
    </Info>
  </Step>

  <Step title="依你的使用情境建立並設定卡片" icon="credit-card">
    使用 `createVirtualCard` 發卡。輸入中的設定會將通用卡片轉為專用卡片 —— 請選擇符合你目標的模式：

    <Tabs>
      <Tab title="一次性購買">
        僅供一筆交易使用的卡片。將 `spendLimit` 設為購買金額，並將 `lockCardNextUse: true`，使卡片在第一次授權後自動鎖定 —— 之後無法再被請款。

        ```json Variables theme={null}
                {
                  "input": {
                    "idempotencyKey": "07df5653-43a8-4532-9881-3ab5857bbe12",
                    "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                    "spendLimit": 150.00,
                    "lockCardNextUse": true,
                    "cardNickname": "Vendor payment — Acme invoice #1042"
                  }
                }
        ```
      </Tab>

      <Tab title="具每月上限的訂閱">
        專用於單一循環扣款的卡片。`spendLimitDuration: MONTHLY` 會在每月重置上限，因此超過上限的漲價或重複請款會自動被拒。

        ```json Variables theme={null}
                {
                  "input": {
                    "idempotencyKey": "07df5653-43a8-4532-9881-3ab5857bbe13",
                    "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                    "spendLimit": 29.99,
                    "spendLimitDuration": "MONTHLY",
                    "cardNickname": "SaaS — analytics subscription"
                  }
                }
        ```
      </Tab>

      <Tab title="有預算且限期的卡片">
        用於專案或旅程且有明確結束日期的卡片。`lockDate` 會在該日凍結卡片（預設為建立後 47 個月），並停用 `usePrepaymentBalance` / `useRewardsBalance` 使其僅從指定的消費帳戶撥款 —— 可預期、單一來源的資金，利於清楚對帳。

        ```json Variables theme={null}
                {
                  "input": {
                    "idempotencyKey": "07df5653-43a8-4532-9881-3ab5857bbe14",
                    "offerId": "ed669305-5e43-40a0-9a25-7a15ed174628",
                    "spendLimit": 2000.00,
                    "lockDate": "2026-09-30",
                    "userCashBalanceId": "<SPEND_ACCOUNT_ID>",
                    "usePrepaymentBalance": false,
                    "useRewardsBalance": false,
                    "cardNickname": "Q3 conference travel"
                  }
                }
        ```
      </Tab>
    </Tabs>

    以上三種皆呼叫相同的 mutation：

    <CodeGroup>
      ```graphql Mutation theme={null}
          mutation createVirtualCard($input: CreateVirtualCardInput!) {
            createVirtualCard(input: $input) {
              virtualCardId
              cardholderName
              virtualCardLast4
              expiryMonth
              expiryYear
              status
              cardType
              initialAmount
              usedAmount
              createdAt
            }
          }
      ```

      ```json Sample response theme={null}
          {
            "data": {
              "createVirtualCard": {
                "virtualCardId": "07df5653-43a8-4532-9881-3ab5857bbe11",
                "cardholderName": "xyz789",
                "virtualCardLast4": "7890",
                "expiryMonth": "12",
                "expiryYear": "27",
                "status": "ACTIVE",
                "cardType": "MULTI_USE",
                "initialAmount": 150.00,
                "usedAmount": 0,
                "createdAt": "2026-07-09T10:00:00Z"
              }
            }
          }
      ```
    </CodeGroup>

    #### 設定總覽

    <ParamField body="spendLimit" type="Float" required>
      卡片可被請款的最高金額 —— 你只會為實際使用的部分付費。必須符合你所選期間的方案上限。
    </ParamField>

    <ParamField body="spendLimitDuration" default="LIFETIME" type="VirtualCardSpendLimitDuration">
      上限如何重設。`LIFETIME` 對總消費設上限；`DAILY` / `WEEKLY` / `MONTHLY` 會形成滾動預算 —— 適合訂閱與團隊額度。
    </ParamField>

    <ParamField body="lockCardNextUse" default="false" type="Boolean">
      在首次成功使用後鎖定卡片 —— 針對一次性供應商付款的「虛擬單次使用卡」模式。
    </ParamField>

    <ParamField body="lockDate" default="自建立日起 47 個月" type="String">
      卡片凍結的 `yyyy-mm-dd` 日期。將卡片的可用期限定在某個專案、行程或合約期間。
    </ParamField>

    <ParamField body="primaryFundingSource" default="FLUZ_BALANCE" type="VirtualCardFundingSource">
      消費的資金來源。`FLUZ_BALANCE` 使用你預先加值的餘額；`BANK_ACCOUNT` 從已連結的銀行帳戶扣款（需要 `bankAccountId`）。
    </ParamField>

    <ParamField body="usePrepaymentBalance / useRewardsBalance" default="true" type="Boolean">
      依預設，卡片也可能從預付（禮品卡）與回饋餘額扣款。將兩者都設為 `false` 可建立僅使用現金、且只從指定 `userCashBalanceId` 撥款的卡片 —— 對會計最清晰。
    </ParamField>

    <ParamField body="memo / transactionCategory" type="String">
      附加在交易上的可選費用備註與類別 —— 類別會在首次使用時建立。參見 [Add Expense Details](/features/add-expense-details)。
    </ParamField>

    <Note>
      **帳單地址：** 若你的帳戶尚未留存，請傳入 `billingAddress`（或已儲存的 `userAddressId`）。必須是可投遞的真實 **美國** 地址 —— 不可為郵政信箱（PO Box）—— 否則建立會以 `VC-0025` 失敗。參見 [Address Formatting Requirements](/concepts/address-formatting-requirements)。
    </Note>

    <Info>
      請保留回應中的 `virtualCardId` —— 下一步你會用它來揭露卡片。若建立失敗，請檢查 [Virtual Card Error Codes](/features/virtual-card-error-codes)。
    </Info>
  </Step>

  <Step title="揭露卡片詳細資料" icon="eye">
    建立回應刻意不包含敏感號碼。請使用 `revealVirtualCardByVirtualCardId` 取得完整的 PAN、CVV 與到期資訊 —— 這些是你（或你的使用者）在結帳時輸入，或新增至行動錢包所需的資料。

    <CodeGroup>
      ```graphql Mutation theme={null}
          mutation RevealVirtualCard($virtualCardId: UUID!) {
            revealVirtualCardByVirtualCardId(virtualCardId: $virtualCardId) {
              cardNumber
              expiryMMYY
              cvv
              cardHolderName
              billingAddress {
                streetAddress
                postalCode
                city
                state
              }
            }
          }
      ```

      ```json Variables theme={null}
          {
            "virtualCardId": "07df5653-43a8-4532-9881-3ab5857bbe11"
          }
      ```
    </CodeGroup>

    需要 `REVEAL_VIRTUALCARD` scope。

    <Warning>
      回應會以明文包含完整卡號與 CVV。請視為敏感持卡人資料 —— 僅透過 TLS 傳輸、切勿記錄於日誌，並僅顯示給授權使用者。
    </Warning>

    <Tip>
      多數線上結帳不需要 PIN —— 但若你的情境需要（或你想使用感應支付），請參見 [Set Virtual Card PIN](/set-virtual-card-pin) 與 [Digital Wallet Push Provisioning](/digital-wallet-push-provisioning)，以一鍵將卡片加入 Apple Pay 或 Google Pay。
    </Tip>
  </Step>

  <Step title="進行消費，然後觀察活動" icon="receipt">
    在卡片網路可被接受之處，於你設定的限制內使用該卡。接著使用 `getVirtualCardTransactions` 拉取卡片活動以確認請款 —— 相同查詢也能支援消費儀表板、對帳與拒付監控。

    <CodeGroup>
      ```graphql Query theme={null}
          query GetVirtualCardTransactions {
            getVirtualCardTransactions(
              input: {
                virtualCardIds: ["07df5653-43a8-4532-9881-3ab5857bbe11"]
                filters: { transactionTypes: [PURCHASE, REFUND, DECLINE] }
                paginate: { limit: 20, offset: 0 }
              }
            ) {
              virtualCardId
              transactions {
                transactionDate
                transactionType
                transactionStatus
                transactionAmount
                merchantName
                mcc
              }
            }
          }
      ```

      ```json Sample response theme={null}
          {
            "data": {
              "getVirtualCardTransactions": [
                {
                  "virtualCardId": "07df5653-43a8-4532-9881-3ab5857bbe11",
                  "transactions": [
                    {
                      "transactionDate": "2026-07-09T14:22:31Z",
                      "transactionType": "PURCHASE",
                      "transactionStatus": "CLEARED",
                      "transactionAmount": 42.17,
                      "merchantName": "ACME OFFICE SUPPLY",
                      "mcc": 5943
                    }
                  ]
                }
              ]
            }
          }
      ```
    </CodeGroup>

    需要 `PCI_COMPLIANCE` 與 `REVEAL_VIRTUALCARD` scopes。省略 `virtualCardIds` 可拉取該帳戶下所有卡片的活動，並可用日期範圍過濾以建立對帳單式檢視。完整參考： [Get Virtual Card Transactions](/features/get-virtual-card-transactions)。

    <Accordion title="用完了嗎？鎖卡吧（lockVirtualCard）" icon="lock">
      設有 `lockCardNextUse` 或 `lockDate` 的卡片會自動處理。若要隨選鎖定其他卡：

      ```graphql theme={null}
            mutation {
              lockVirtualCard(input: { virtualCardId: "07df5653-43a8-4532-9881-3ab5857bbe11" }) {
                virtualCardId
                locked
              }
            }
      ```

      需要 `EDIT_VIRTUALCARD` scope。鎖定是可逆的 —— 參見 [Unlock Virtual Card](/features/unlock-virtual-card)。
    </Accordion>
  </Step>
</Steps>

## 全部完成 🎉

你已針對特定任務發出一張虛擬卡 —— 選定方案、設定消費控管、揭露卡片並追蹤其活動。接下來可更深入：

<CardGroup cols={2}>
  <Card title="編輯、鎖定與管理卡片" icon="pencil" href="/features/edit-virtual-card">
    變更現有卡片的上限、暱稱與鎖定日期。
  </Card>

  <Card title="數位錢包與 PIN" icon="smartphone" href="/digital-wallet-push-provisioning">
    將卡片推送至 Apple Pay / Google Wallet 並設定 PIN。
  </Card>

  <Card title="大量發卡" icon="layers" href="/features/create-bulk-order">
    一次建立最多 10,000 張卡。
  </Card>

  <Card title="將卡片發送給他人" icon="send" href="/features/send-cards">
    透過連結、電子郵件或簡訊分發卡片給收件者。
  </Card>
</CardGroup>

<Note>
  **想了解更多？** 歡迎聯絡我們： [support@fluz.app](mailto:support@fluz.app) 與專家對談或預約示範。
</Note>
