> ## 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.

# Send a Card to Someone

> Generate a hosted virtual card link, watch the recipient claim it, and manage the link lifecycle — end to end in the sandbox.

This Quickstart walks through the complete Send Cards lifecycle. You'll create a staging application, mint a scoped Bearer token, choose a card program, retrieve a funded spend account, generate hosted virtual card links, experience the recipient activation flow, verify issuance, then deactivate an unused link.

By the end you'll have successfully completed every public Send Cards operation:

* `generateVCShareLinks`
* `getVCShareLinks`
* `deactivateVCShareLinks`

—all in the sandbox, where no real customer funds move.

<Info>
  **Prerequisites**

  * A **Fluz account** — you'll create staging API credentials and mint a scoped access token in Steps 1–2 below.
  * Requests go to the **sandbox** GraphQL endpoint. Hosted recipient links use the standard Fluz activation experience, but all API operations use your staging environment.
  * Your account must have **Send Cards enabled** (`send_virtual_cards_enabled`) or every Send Cards operation returns a permissions error.
  * This Quickstart uses a funded **Spend Account** as the funding source. Cards are funded **when claimed**, not when links are generated.
</Info>

## Before you begin

Except for minting your token (Step 2), every request in this guide is sent to the Fluz GraphQL API using your Bearer access token.

<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 { offerId programName rewardValue } }"
    }'
  ```
</CodeGroup>

<Tip>
  Every GraphQL operation below uses this endpoint and your Bearer token. The only exception is Step 2, which exchanges your application credentials for an access token through the OAuth service.
</Tip>

## The full flow

<Steps>
  <Step title="Create a staging application" icon="user-plus">
    Create a Fluz account, then open the Developer Console and create a **Staging** application.

    When your application is created you'll receive:

    * `clientId`
    * `clientSecret`

    Copy both values somewhere safe. Your `clientSecret` is only shown once.

    If you haven't already created a staging application, see [Prepare your accounts](/get-started/prepare-accounts).
  </Step>

  <Step title="Exchange your credentials for a scoped Bearer token" icon="key">
    Send your application credentials to the OAuth service to generate a short-lived user access token.

    This token authorizes every Send Cards operation that follows.

    <CodeGroup>
      ```bash Mint access 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":[
              "CREATE_SHARE_LINK",
              "LIST_PAYMENT"
            ]
          }
      }'
      ```

      ```json Response theme={null}
      {
        "data": {
          "generateUserAccessToken": {
            "accessToken": "eyJhbGciOi...",
            "expiresIn": 3600,
            "scopes": [
              "CREATE_SHARE_LINK",
              "LIST_PAYMENT"
            ]
          }
        }
      }
      ```
    </CodeGroup>

    Save the returned `accessToken`.

    You'll use it as:

    ```http theme={null}
    Authorization: Bearer <YOUR_USER_ACCESS_TOKEN>
    ```

    for every remaining request.

    <Info>
      `CREATE_SHARE_LINK` authorizes every Send Cards operation.

      This Quickstart also requests `LIST_PAYMENT` so you can retrieve the Spend Account that funds your hosted cards.
    </Info>

    <Warning>
      **Never expose your** `clientSecret `**inside a browser or mobile application.**

      Generate Bearer tokens server-side and forward only the access token to your client.
    </Warning>
  </Step>

  <Step title="Retrieve a funded Spend Account" icon="wallet">
    Hosted virtual cards are funded from one of your **Spend Accounts**.

    Unlike regular virtual cards, **no funds are reserved when the link is generated.**

    Instead, the selected Spend Account is charged only when the recipient successfully claims the card.

    Retrieve your available Spend Accounts.

    <CodeGroup>
      ```graphql Query theme={null}
      query GetSpendAccounts {
        getSpendAccounts {
          userCashBalanceId
          nickname
          availableBalance
          currency
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "getSpendAccounts": [
            {
              "userCashBalanceId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
              "nickname": "Primary Spend Account",
              "availableBalance": 5000,
              "currency": "USD"
            }
          ]
        }
      }
      ```
    </CodeGroup>

    Save the `userCashBalanceId`.

    You'll supply this value when generating your hosted card links.

    <Note>
      The selected Spend Account must belong to your account and must contain sufficient funds **when the recipient claims the card**. If there isn't enough available balance at claim time, card issuance fails.
    </Note>
  </Step>

  <Step title="Choose the card program" icon="layers">
    Every hosted card is issued against a virtual card **offer**.

    The offer determines the issuing program, available rewards, and the limits that apply to every generated card.

    Retrieve the offers available to your account.

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

      ```json Response theme={null}
      {
        "data": {
          "getVirtualCardOffers": [
            {
              "offerId": "11111111-2222-3333-4444-555555555555",
              "programName": "Virtual Card",
              "rewardValue": "1.5%",
              "programLimits": {
                "dailyLimit": 500,
                "weeklyLimit": 2000,
                "monthlyLimit": 5000
              }
            }
          ]
        }
      }
      ```
    </CodeGroup>

    Save the `offerId` for the program you'd like to issue against.

    <Info>
      **The selected offer must be:**

      * active
      * share-enabled

      If generation fails because the offer isn't eligible for Send Cards, confirm with your Fluz representative which offers are enabled for hosted sharing.
    </Info>
  </Step>

  <Step title="Generate two hosted card links" icon="link">
    You're ready to create hosted Send Card links.

    Each generated link represents **one future virtual card**.

    At this stage:

    * No card has been issued.
    * No funds have been withdrawn.
    * Each link begins in the `PENDING` state.

    The selected Spend Account is charged **only when a recipient claims a link**.

    For this Quickstart we'll generate **two** links:

    * **Link A** — you'll claim this as the recipient.
    * **Link B** — you'll leave unclaimed so it can later be revoked.

    <CodeGroup>
      ```graphql Mutation theme={null}
      mutation GenerateVCShareLinks($input: GenerateVCShareLinksInput!) {
        generateVCShareLinks(input: $input) {
          shareLinks
        }
      }
      ```

      ```json Variables theme={null}
      {
        "input": {
          "cardLimit": 25,
          "offerId": "<OFFER_ID>",
          "quantity": 2,
          "daysUntilExpiration": 14,
          "shareMethod": "GENERATE_URL",
          "userCashBalanceId": "<USER_CASH_BALANCE_ID>"
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "generateVCShareLinks": {
            "shareLinks": [
              "https://fluz.app/virtual-prepaid-card/3f8ac...c1",
              "https://fluz.app/virtual-prepaid-card/9b2dd...77"
            ]
          }
        }
      }
      ```
    </CodeGroup>

    The response returns one hosted activation URL for every generated card.

    Save both URLs.

    We'll refer to them as:

    * **Link A**
    * **Link B**

    throughout the remainder of this Quickstart.

    ### Understanding the generation settings

    <ParamField body="cardLimit" type="Int" required>
      The amount loaded onto each hosted card when it's claimed.

      Each generated card receives its own independent limit.
    </ParamField>

    <ParamField body="offerId" type="UUID" required>
      The hosted virtual card program to issue against.

      The offer must be active and enabled for Send Cards.
    </ParamField>

    <ParamField body="quantity" type="Int" required>
      The number of hosted links to generate.

      One share request and one hosted URL are created for every requested quantity.
    </ParamField>

    <ParamField body="shareMethod" type="ShareMethodType" required>
      Controls how recipients receive their links.

      * `GENERATE_URL` returns hosted URLs for you to distribute.
      * `EMAIL` emails recipients automatically.
      * `PHONE_NUMBER` sends recipients an SMS.
    </ParamField>

    <ParamField body="userCashBalanceId" type="UUID" required>
      The Spend Account that funds every generated card.

      Although this field appears optional in the GraphQL schema, it is required in practice.
    </ParamField>

    <ParamField body="daysUntilExpiration" type="Int">
      How long recipients have to claim the hosted link.

      If omitted, the program default is used.

      The resulting expiration date also becomes the issued card's lock date.
    </ParamField>

    <Accordion title="Deliver cards by email or SMS instead" icon="mail">
      Instead of distributing hosted URLs yourself, Fluz can send every recipient their own activation link.

      ### Email

      ```json theme={null}
      {
        "input": {
          "cardLimit": 25,
          "offerId": "<OFFER_ID>",
          "quantity": 2,
          "shareMethod": "EMAIL",
          "recipientListEmail": [
            "alice@example.com",
            "bob@example.com"
          ],
          "userCashBalanceId": "<USER_CASH_BALANCE_ID>"
        }
      }
      ```

      ### SMS

      ```json theme={null}
      {
        "input": {
          "cardLimit": 25,
          "offerId": "<OFFER_ID>",
          "quantity": 2,
          "shareMethod": "PHONE_NUMBER",
          "recipientListPhone": [
            "+18883606660",
            "+18885551234"
          ],
          "userCashBalanceId": "<USER_CASH_BALANCE_ID>"
        }
      }
      ```

      Recipient list length **must exactly equal** `quantity`.

      If they don't match, validation fails and **no links are created**.

      Phone numbers must:

      * include the country code
      * contain no spaces
      * be supplied as strings

      Example:

      ```text theme={null}
      +18883606660
      ```
    </Accordion>

    <Warning>
      **Generating hosted links does not reserve funds.**

      If the selected Spend Account doesn't contain sufficient available balance when the recipient claims the card, card issuance fails.
    </Warning>

    <Info>
      **The generation response intentionally returns only the hosted URLs.**

      It does **not** return:

      * `shareRequestBatchId`
      * `shareRequestDisplayId`

      You'll retrieve those in the next step.
    </Info>
  </Step>

  <Step title="Retrieve the generated share requests" icon="list-checks">
    Although you already have the hosted URLs, you'll usually also want the underlying share request records.

    These contain:

    * lifecycle status
    * batch identifiers
    * display IDs
    * issued virtual card IDs
    * expiration information

    Immediately after generation, retrieve your pending share requests.

    <CodeGroup>
      ```graphql Query theme={null}
      query GetVCShareLinks($input: GetVCShareLinksInput!) {
        getVCShareLinks(input: $input) {
          shareRequestBatchId
          shareRequestDisplayId
          shareObjectStatus
          linkExpirationDate
          virtualCardId
          linkUrl
        }
      }
      ```

      ```json Variables theme={null}
      {
        "input": {
          "shareObjectStatuses": [
            "PENDING"
          ]
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "getVCShareLinks": [
            {
              "shareRequestBatchId": "BATCH123",
              "shareRequestDisplayId": "SR-000001",
              "shareObjectStatus": "PENDING",
              "virtualCardId": null,
              "linkExpirationDate": "2026-08-01T00:00:00Z",
              "linkUrl": "https://fluz.app/virtual-prepaid-card/3f8ac...c1"
            },
            {
              "shareRequestBatchId": "BATCH123",
              "shareRequestDisplayId": "SR-000002",
              "shareObjectStatus": "PENDING",
              "virtualCardId": null,
              "linkExpirationDate": "2026-08-01T00:00:00Z",
              "linkUrl": "https://fluz.app/virtual-prepaid-card/9b2dd...77"
            }
          ]
        }
      }
      ```
    </CodeGroup>

    Match each returned `linkUrl` with the URLs returned during generation.

    Save:

    * the shared `shareRequestBatchId`
    * both `shareRequestDisplayId` values

    You'll use them later when deactivating the unused link.

    At this point both links should have:

    ```text theme={null}
    Status: PENDING
    Virtual Card ID: null
    ```

    which confirms that:

    * the links were created successfully
    * no recipient has claimed them yet
    * no virtual cards have been issued
  </Step>

  <Step title="Claim one link as the recipient" icon="smartphone">
    Open **Link A** in your browser.

    This is exactly the experience your recipient sees.

    The hosted flow guides recipients through card activation without requiring any API integration.

    During activation the recipient:

    1. Opens the hosted activation page.
    2. Signs in or creates a Fluz account.
    3. Completes identity verification.
    4. Completes two-factor authentication.
    5. Adds a billing address if one isn't already on file.
    6. Creates a card PIN.
    7. Receives their hosted virtual card.

    Only after the final step does Fluz:

    * issue the virtual card
    * fund it from your Spend Account
    * assign it to the recipient

    The recipient becomes the authorized holder of **that card only**.

    They do **not** gain access to:

    * your Fluz account
    * your Spend Accounts
    * your balances
    * any other generated cards

    Once issued, the recipient can:

    * view the card
    * spend online
    * add it to Apple Pay or Google Wallet (where supported)
    * view future transactions

    <Info>
      **Leave Link B untouched.**

      We'll use it to demonstrate link revocation in the next section.
    </Info>
  </Step>

  <Step title="Verify the card was issued" icon="badge-check">
    After the recipient claims **Link A**, retrieve the share requests again.

    This time you'll see the claimed link transition from `PENDING` to `ISSUED`.

    <CodeGroup>
      ```graphql Query theme={null}
      query GetVCShareLinks($input: GetVCShareLinksInput!) {
        getVCShareLinks(input: $input) {
          shareRequestDisplayId
          shareObjectStatus
          virtualCardId
          linkUrl
        }
      }
      ```

      ```json Variables theme={null}
      {
        "input": {
          "shareRequestBatchIds": [
            "BATCH123"
          ]
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "getVCShareLinks": [
            {
              "shareRequestDisplayId": "SR-000001",
              "shareObjectStatus": "ISSUED",
              "virtualCardId": "c8dbe6d8-2f2f-4c90-8d7e-15ef5b06e387",
              "linkUrl": "https://fluz.app/virtual-prepaid-card/3f8ac...c1"
            },
            {
              "shareRequestDisplayId": "SR-000002",
              "shareObjectStatus": "PENDING",
              "virtualCardId": null,
              "linkUrl": "https://fluz.app/virtual-prepaid-card/9b2dd...77"
            }
          ]
        }
      }
      ```
    </CodeGroup>

    Your two links should now be in different lifecycle states.

    | Link       | Expected status | Meaning                                                                          |
    | ---------- | --------------- | -------------------------------------------------------------------------------- |
    | **Link A** | `ISSUED`        | The recipient successfully claimed the card and a virtual card has been created. |
    | **Link B** | `PENDING`       | The link has not yet been claimed.                                               |

    The appearance of a `virtualCardId` confirms that card issuance has completed successfully.

    <Accordion title="Understanding Send Card statuses" icon="info">
      Every hosted Send Card progresses through one of four lifecycle states.

      | Status    | Meaning                                                                    |
      | --------- | -------------------------------------------------------------------------- |
      | `PENDING` | The hosted link has been generated but hasn't yet been claimed.            |
      | `ISSUED`  | The recipient successfully claimed the link and received a virtual card.   |
      | `USED`    | The issued card has completed at least one transaction.                    |
      | `EXPIRED` | The hosted link expired naturally or was deactivated before being claimed. |

      Only links in the `PENDING` state can be deactivated.

      Once a card reaches `ISSUED`, deactivating the original link does **not** revoke the card.
    </Accordion>
  </Step>

  <Step title="Deactivate the unused link" icon="lock">
    Suppose the second recipient never needed their card, or a batch was generated accidentally.

    You can revoke any **unclaimed** hosted link using either:

    * `shareRequestBatchIds`
    * `shareRequestDisplayIds`

    For this Quickstart we'll deactivate only **Link B** using its display ID.

    <CodeGroup>
      ```graphql Mutation theme={null}
      mutation DeactivateVCShareLinks($input: DeactivateVCShareLinksInput!) {
        deactivateVCShareLinks(input: $input)
      }
      ```

      ```json Variables theme={null}
      {
        "input": {
          "shareRequestDisplayIds": [
            "SR-000002"
          ]
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "deactivateVCShareLinks": "1 share requests successfully deactivated!"
        }
      }
      ```
    </CodeGroup>

    Deactivation immediately prevents the hosted link from ever being claimed.

    If a recipient later opens the link they'll receive an expired or revoked experience instead of the activation flow.

    <Warning>
      Deactivation only affects **unclaimed** links.

      If a recipient has already claimed a card (`ISSUED` or `USED`), the hosted link can no longer be used to revoke it.

      To stop spend on an issued card, use the appropriate virtual card lifecycle controls such as [Lock Virtual Card](/features/lock-virtual-card).
    </Warning>
  </Step>

  <Step title="Confirm the final lifecycle" icon="clipboard-check">
    Retrieve the share requests one final time.

    <CodeGroup>
      ```graphql Query theme={null}
      query GetVCShareLinks($input: GetVCShareLinksInput!) {
        getVCShareLinks(input: $input) {
          shareRequestDisplayId
          shareObjectStatus
          virtualCardId
        }
      }
      ```

      ```json Variables theme={null}
      {
        "input": {
          "shareRequestBatchIds": [
            "BATCH123"
          ]
        }
      }
      ```

      ```json Response theme={null}
      {
        "data": {
          "getVCShareLinks": [
            {
              "shareRequestDisplayId": "SR-000001",
              "shareObjectStatus": "ISSUED",
              "virtualCardId": "c8dbe6d8-2f2f-4c90-8d7e-15ef5b06e387"
            },
            {
              "shareRequestDisplayId": "SR-000002",
              "shareObjectStatus": "EXPIRED",
              "virtualCardId": null
            }
          ]
        }
      }
      ```
    </CodeGroup>

    You've now exercised the complete Send Cards lifecycle.

    | Link       | Final status | Result                                           |
    | ---------- | ------------ | ------------------------------------------------ |
    | **Link A** | `ISSUED`     | Successfully claimed and issued to a recipient.  |
    | **Link B** | `EXPIRED`    | Successfully revoked before it could be claimed. |

    At this point you've successfully used all three public Send Cards operations:

    * ✅ `generateVCShareLinks`
    * ✅ `getVCShareLinks`
    * ✅ `deactivateVCShareLinks`
  </Step>
</Steps>

## You're done 🎉

You've completed the full hosted Send Cards lifecycle—from generation through recipient activation, lifecycle tracking, and link revocation.

Along the way you:

* Generated hosted virtual card links.
* Selected the Spend Account that funds recipient cards.
* Retrieved and tracked share request records.
* Claimed a hosted card as the recipient.
* Verified the transition from `PENDING` to `ISSUED`.
* Revoked an unused hosted link.
* Confirmed the final `EXPIRED` state.

From here you can explore more advanced Send Cards workflows.

<CardGroup cols={2}>
  <Card title="Send Cards overview" icon="send" href="/features/send-cards">
    Recipient experience, program rules, lifecycle states, and complete error reference.
  </Card>

  <Card title="Generate Share Links" icon="link" href="/features/generate-share-links">
    The detailed API reference for every Send Cards operation.
  </Card>

  <Card title="Get Spend Accounts" icon="wallet" href="/features/get-spend-accounts">
    Retrieve and manage the Spend Accounts used to fund hosted cards.
  </Card>

  <Card title="Manage Virtual Cards" icon="credit-card" href="/features/lock-virtual-card">
    Lock and manage cards after they've been issued to recipients.
  </Card>
</CardGroup>

<Note>
  **Want to learn more?**

  Contact us at [support@fluz.app](mailto:support@fluz.app) to speak with our experts or request a demo.
</Note>
