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

> Send money from a user's cash balance to an email address, a phone number, a Fluz account, or a claim link with sendMoney, and cancel a send nobody has claimed.

Use [`sendMoney`](https://docs.fluz.app/api-reference/mutations/send-money) to send money from a user's Fluz cash balance. You can address it to an email address or phone number, to a Fluz account id, or to nobody, in which case you get a claim link to deliver yourself. The recipient doesn't need to be a user of your application, or to have a Fluz account yet.

A send ends one of two ways. `SENT` means the money reached the recipient's balance, and it's final. `PENDING_CLAIM` means Fluz holds the money until the recipient claims it on a Fluz page. If nobody claims it before it expires, or you cancel it, the money goes back to the sender. How you address the send decides which one happens.

> [!NOTE]
>
> **Before you start**
>
> * Call with a Bearer user access token that has the `MAKE_PAYOUT_TRANSFER_SEND` scope. Basic Auth with your API key isn't accepted.
> * The token's user must be an owner or admin of the account.
> * Fluz turns on send money per account. Ask your account team to enable it for each account that sends.
> * The account must have passed identity verification: KYC for a personal account, KYB for a business.
> * If the user limited your application to certain spend accounts, send from one of those.

> [!NOTE]
>
> **Not the same as `createTransfer`.**
>
> [`createTransfer`](https://docs.fluz.app/features/transfer-to-another-fluz-wallet) moves money between your application's account and accounts that have authorized your application, or between two of those accounts. `sendMoney` can pay any Fluz account that can receive payments, or reach someone by email or phone. For a new recipient it holds the money until they claim it, and Fluz sends them the claim link.

## How a send is delivered

| You send to | What happens |
| :- | :- |
| `recipientId` | The money lands in that account right away (`SENT`). If the account can't receive payments, the send is refused. It's never held. |
| `recipientEmail` or `recipientPhone`, and a Fluz user has verified that contact | The money lands in that user's personal account right away (`SENT`). |
| `recipientEmail` or `recipientPhone` that matches no Fluz user, or a user who hasn't verified it | Fluz holds the money (`PENDING_CLAIM`) and sends the recipient a claim link at the contact you gave. |
| `linkOnly: true` | Fluz holds the money (`PENDING_CLAIM`) and returns a `claimLink`. Fluz contacts nobody, so you deliver the link. |

Fluz matches the email address and phone number on a user's Fluz profile. If either matches more than one user, the send is refused, and you need a different identifier.

You can pass `recipientEmail` and `recipientPhone` together for the same person. If both match one user, the phone decides: the money lands right away only if that user has verified the phone. If they match two different users, Fluz holds the money instead of choosing. If only one of them matches a user, that contact decides on its own: if the user verified it, the money lands in their account right away, even though the other contact matches nobody.

`recipientId` can't be combined with an email or phone, and `linkOnly` can't be combined with any recipient. You can't send to the sender's own account.

A send that would land right away but can't, for example because the recipient's account can't receive payments or the amount is over a limit, fails with an error. Fluz doesn't hold it instead.

## Send money

The same mutation covers every kind of send. Only the input changes.

```graphql Mutation theme={null}
mutation SendMoney($input: SendMoneyInput!) {
  sendMoney(input: $input) {
    result
    transferId
    destinationAccountId
    shareRequestId
    claimLink
    claimStatus
  }
}
```

### To an email address or phone number

```json Variables theme={null}
{
  "input": {
    "idempotencyKey": "6f2b8c1e-4d3a-4f7b-9a21-3c5e8d9f0a12",
    "amount": 25,
    "sourceCashBalanceId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
    "recipientEmail": "alex@example.com",
    "memo": "Dinner on Friday"
  }
}
```

```json Response (held) theme={null}
{
  "data": {
    "sendMoney": {
      "result": "PENDING_CLAIM",
      "transferId": "c56a4180-65aa-42ec-a945-5fd21dec0538",
      "destinationAccountId": null,
      "shareRequestId": "0b8f2a5e-7c41-4d9e-8f3a-2e6b9c1d4a70",
      "claimLink": "https://fluz-links.short.gy/Xy7Kq2",
      "claimStatus": "PENDING"
    }
  }
}
```

```json Response (sent) theme={null}
{
  "data": {
    "sendMoney": {
      "result": "SENT",
      "transferId": "c56a4180-65aa-42ec-a945-5fd21dec0538",
      "destinationAccountId": "a2c02ec6-357b-41cf-9229-4da34e727019",
      "shareRequestId": null,
      "claimLink": null,
      "claimStatus": null
    }
  }
}
```

`claimLink` is a short link to the claim page. Use it exactly as returned, without building or parsing it.

To send to a phone number, pass `recipientPhone` in E.164 format, such as `+14155551234`, instead of `recipientEmail`.

### To a Fluz account

Pass the recipient's account id. The send lands right away or is refused.

```json Variables theme={null}
{
  "input": {
    "idempotencyKey": "3d1f9a7c-2b5e-4c8d-a6f0-7e9b1c2d3a45",
    "amount": 40.5,
    "sourceCashBalanceId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
    "recipientId": "a2c02ec6-357b-41cf-9229-4da34e727019"
  }
}
```

### As a claim link

Set `linkOnly` and deliver `claimLink` yourself, for example in your own app or message.

```json Variables theme={null}
{
  "input": {
    "idempotencyKey": "9a4e2c7b-1f3d-4b6a-8c5e-0d2f4a6b8c1e",
    "amount": 15,
    "sourceCashBalanceId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
    "linkOnly": true
  }
}
```

> [!WARNING]
>
> **Treat the claim link like a password.**
>
> Anyone who has a link-only send's `claimLink` can claim the money once they pass identity verification. Its `shareRequestId` is just as sensitive, because the claim page can be reached with it. Keep both out of logs and analytics.

## Input fields

[`SendMoneyInput`](https://docs.fluz.app/api-reference/types/send-money-input)

| Field | Type | Required | Description |
| :- | :- | :- | :- |
| `idempotencyKey` | `UUID!` | Yes | A UUID you generate for each new send. See [Idempotency](#idempotency). |
| `amount` | `Float!` | Yes | Greater than 0, at most 1,000,000, with at most two decimal places. |
| `sourceCashBalanceId` | `UUID!` | Yes | The `userCashBalanceId` of the spend account that pays, from [`getUserCashBalances`](https://docs.fluz.app/features/get-spend-accounts), which needs the `LIST_PAYMENT` scope. It must be an active spend account on the token's account. |
| `recipientEmail` | `String` | Choose one | The recipient's email address. |
| `recipientPhone` | `String` | Choose one | The recipient's phone number in E.164 format. |
| `recipientId` | `UUID` | Choose one | The recipient's Fluz account id. |
| `linkOnly` | `Boolean` | Choose one | `true` to get a claim link with no addressee. |
| `memo` | `String` | No | A note for the recipient, at most 255 characters. It can't start with `=`, `+`, `-`, `@`, a tab or a carriage return, even after leading whitespace. |
| `daysUntilExpiration` | `Int` | No | Days a held send can be claimed, 1 to 365. Defaults to 30. |

Address the send with `recipientEmail`, `recipientPhone` or both, with `recipientId`, or with `linkOnly`.

On a held send, the memo appears on the claim page, where anyone who opens the link can read it, even after the send is claimed or returned. Keep personal details out of it.

## Response fields

[`SendMoneyResponse`](https://docs.fluz.app/api-reference/types/send-money-response)

| Field | Type | Description |
| :- | :- | :- |
| `result` | `MoneySendResult!` | `SENT` or `PENDING_CLAIM`. |
| `transferId` | `UUID` | The transfer that moved the money, or that holds it while the send waits. |
| `destinationAccountId` | `UUID` | The account that received the money. Set only when `result` is `SENT`. |
| `shareRequestId` | `UUID` | Identifies a held send. Pass it to `cancelMoneySend`. Set only when `result` is `PENDING_CLAIM`. It opens the claim page just as `claimLink` does, so keep it out of logs and analytics. |
| `claimLink` | `String` | The link the recipient opens to claim. Returned only while `claimStatus` is `PENDING`. |
| `claimStatus` | `MoneySendClaimStatus` | Where a held send stands now. See [Track a held send](#track-a-held-send). |

## What the recipient does

Claiming happens on a Fluz page, not through the API.

**1. Open the link**

Fluz sends the claim link to the email address or phone number you sent to. For a link-only send, you deliver it.

**2. Sign in or create a Fluz account**

The money goes to the account they're signed in to when they claim, personal or business.

**3. Verify their identity**

The account must pass KYC for a personal account or KYB for a business, and be able to receive payments.

**4. Prove the contact**

For a send to a phone number, the phone on their Fluz account must match it and be verified. For a send to an email address, Fluz emails a 6-digit code to that address. If you sent to both, a verified matching phone is enough. If their account's phone matches but isn't verified, they verify it first. Otherwise they enter the email code. A link-only send needs only the link.

The claim page shows the amount, the sender's name and the memo to anyone who opens the link, before they sign in.

When someone claims, Fluz checks the sender's account again. If it no longer passes KYC or KYB, or Fluz has restricted it, the claim is refused and the money stays held until you cancel the send or it expires. Turning off send money for an account doesn't stop its held sends from being claimed, so cancel any you want to stop.

## Track a held send

To check where a held send stands, call `sendMoney` again with the same `idempotencyKey` and the same input. The response repeats the original result and ids with the current `claimStatus`, includes `claimLink` only while `claimStatus` is `PENDING`, and moves no money.

| `claimStatus` | Meaning |
| :- | :- |
| `PENDING` | Waiting for the recipient. You can cancel it. |
| `CLAIMING` | Reserved. A claim moves a send from `PENDING` straight to `CLAIMED`. |
| `CLAIMED` | The recipient claimed it, and the money is in their balance. |
| `RETURNED` | It expired or was cancelled, and the money went back to the sender. |

The repeat call runs the same scope, role and spend account checks as a new send, so it's refused if the user is no longer an owner or admin, or if your application can no longer use the spend account.

## Cancel a held send

[`cancelMoneySend`](https://docs.fluz.app/api-reference/mutations/cancel-money-send) cancels a send while its `claimStatus` is `PENDING` and returns the money to the cash balance it came from. A `SENT` send can't be cancelled.

```graphql Mutation theme={null}
mutation CancelMoneySend($shareRequestId: UUID!, $idempotencyKey: UUID!) {
  cancelMoneySend(shareRequestId: $shareRequestId, idempotencyKey: $idempotencyKey) {
    cancelled
    transferId
  }
}
```

```json Variables theme={null}
{
  "shareRequestId": "0b8f2a5e-7c41-4d9e-8f3a-2e6b9c1d4a70",
  "idempotencyKey": "4c7e1a9b-6d2f-4e8a-b3c5-1f9d7a2e6b40"
}
```

```json Response theme={null}
{
  "data": {
    "cancelMoneySend": {
      "cancelled": true,
      "transferId": "c56a4180-65aa-42ec-a945-5fd21dec0538"
    }
  }
}
```

Cancelling needs the same scope, and the token's user must be an owner or admin of the sending account. You can cancel any held send from the account, including one another user or application sent. A refused cancel comes back as an error, so `cancelled` is always `true`. When the same user repeats a successful cancel of the same send with the same `idempotencyKey` within 24 hours, it gets the same response. A refused cancel isn't stored, so a repeat runs it again.

## Expiry

A held send can be claimed until the end of the day, Eastern time, `daysUntilExpiration` days after it was sent. The response doesn't include that date, so record it when you send.

After that, claims are refused, and Fluz returns the money to the sender's cash balance the next morning, in a daily run at 9:00 Eastern. Until the money is returned, `claimStatus` still reads `PENDING` and you can still cancel the send.

## Idempotency

`sendMoney` and `cancelMoneySend` both take an `idempotencyKey`, a UUID you generate. Letter case doesn't matter.

* A repeat with the same key and the same input returns the original send, moves no money, and shows where the send stands now.
* A key stays tied to its send. Fluz answers repeats from a cache for 24 hours and from the send itself after that, so a key never sends twice. Use a new key for every new send.
* A repeat that changes the amount, the cash balance or the recipient, or sets `linkOnly` on a key used for a recipient, is refused with `ARG-0001`. Never reuse a key from another operation: one used with `createTransfer` makes a new send, and one used for an external payout is refused only if that payout's key was lowercase.
* `memo` and `daysUntilExpiration` aren't compared. A repeat that changes only those returns the original send unchanged.
* `sendMoney` keys belong to the account, not to your application. The same key and input from another application or user on the account returns the original send.
* If a send fails before any money moves, for example because the balance is too low, the key stays free. Fix the cause and retry with the same key.

`G-0409` means Fluz is still working on that key, or its answer was lost. The send may have gone through, so retry with the same key and the same input until you get a result. A request in progress holds its key for up to 10 minutes.

## Limits

Sends count against the account's transfer limits: daily, weekly, monthly and yearly totals, plus a minimum and maximum per send. A held send counts from when it's sent until the money is returned. The recipient's receive limits apply when the money lands, at send for an immediate send and at claim for a held one. Ask your account team for your account's limits.

## Errors

Errors come back in the GraphQL `errors` array with `sendMoney` or `cancelMoneySend` set to `null`. Branch on `extensions.code`. The `ARG-` and `G-0003` messages name the specific reason. Other messages can change.

| Code | When it happens |
| :- | :- |
| `AUTH-0002` | The request used Basic Auth. Use a Bearer user access token. |
| `AUTH-0031` | The token lacks `MAKE_PAYOUT_TRANSFER_SEND`, or your application can't use that cash balance. |
| `AUTH-0008` | The token's user isn't an owner or admin of the account. |
| `G-0003` | `Account is not enabled for money sends`: Fluz hasn't turned on send money for the account. |
| `G-0003` | `Sender is not authorized to send a payment.`: the account hasn't passed KYC or KYB. |
| `G-0003` | `Recipient is not able to receive payments`: the account you sent to with `recipientId` can't receive payments, or the send would pass its receive limits. No reason is given. |
| `ARG-0001`, `ARG-0002` | The input is invalid, and the message names the problem. This includes a send to the sender's own account, a contact that matches more than one user, and a key reused with different input. |
| `PT-0007` | The cash balance doesn't hold enough to cover the amount. |
| `PT-0008` | Part of a personal account's balance is still clearing and can't be sent yet. |
| `US-0042` | `sourceCashBalanceId` isn't one of the account's spend accounts. An id that doesn't exist at all can return `ARG-0001` instead. |
| `CASH-0002` | The recipient has no cash balance that can receive this send. |
| `FLUZ-0113` | The sender's account can't send money right now. |
| `FLUZ-0131`, `FLUZ-0140`, `FLUZ-0132`, `FLUZ-0141` | The send would pass the daily, weekly, monthly or yearly limit. |
| `FLUZ-0142`, `FLUZ-0143` | The amount is below the minimum or above the maximum per send. |
| `G-0409` | The key is still in progress or its answer was lost. Retry with the same key and input. |
| `G-0010` | A Fluz service failed while setting up the recipient of a send to an email address or phone number. No money moved. Retry with the same key and input, and contact your account team if it keeps failing. |
| `G-0004` | Something unexpected failed, or the spend account isn't active. Retry with the same key and input, and check the spend account if it keeps failing. |

A send that lands right away also goes through Fluz's fraud screening, which can refuse it with other codes. On a send to `recipientEmail` or `recipientPhone`, a `FLUZ-` limit code can also mean the recipient's receive limit.

A missing, invalid or revoked token is refused before the operation runs, with HTTP 401, or HTTP 498 once it has expired, and no GraphQL `errors` array.

For `cancelMoneySend`:

| Code | Message | When it happens |
| :- | :- | :- |
| `ARG-0001` | `Money send not found` | The id isn't a money send. |
| `G-0003` | `You are not the sender of this money send` | The send came from another account. |
| `G-0003` | `Money send is not cancellable (status USED)` | The recipient already claimed it. |
| `G-0003` | `Money send is not cancellable (status EXPIRED)` | It was already cancelled or returned. |
| `G-0003` | `Money send escrow was settled concurrently` | The held money was already settled, but the send still reads `PENDING`. Contact your account team with the `shareRequestId`. |

## Reference

* [`sendMoney`](https://docs.fluz.app/api-reference/mutations/send-money) and [`SendMoneyInput`](https://docs.fluz.app/api-reference/types/send-money-input)
* [`SendMoneyResponse`](https://docs.fluz.app/api-reference/types/send-money-response), [`MoneySendResult`](https://docs.fluz.app/api-reference/types/money-send-result) and [`MoneySendClaimStatus`](https://docs.fluz.app/api-reference/types/money-send-claim-status)
* [`cancelMoneySend`](https://docs.fluz.app/api-reference/mutations/cancel-money-send) and [`CancelMoneySendResponse`](https://docs.fluz.app/api-reference/types/cancel-money-send-response)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.