useCapxulPay
Mutation hook for sending money to a validated recipient — instant by default, or a scheduled/streaming Commitment.
Sends money from the signed-in user's Account to a recipient — a handle,
email, organization, or saved payee. For cash-out to a saved destination use
useCapxulPayout; for an external
wallet use useCapxulWithdraw.
Read results back with useCapxulPayments.
Import
import { useCapxulPay } from "@capxul/sdk-react";Usage
"use client";
import { useCapxulPay } from "@capxul/sdk-react";
function PayButton({ email }: { email: string }) {
const pay = useCapxulPay();
return (
<div>
<button
disabled={pay.isPending}
onClick={() =>
pay.mutate({
to: { kind: "email", email },
amount: { currency: "USD", value: "25.00", decimals: 2 },
})
}
>
{pay.isPending ? "Sending…" : "Send $25"}
</button>
{pay.error ? <p>{pay.error.message}</p> : null}
{pay.data ? <p>Payment {pay.data.id} is {pay.data.status}.</p> : null}
</div>
);
}Parameters
The hook itself takes no parameters. The mutation takes a PaymentsPayInput:
Prop
Type
to — the recipient. Recipients are typed references, never raw
addresses. The accepted forms are:
{ kind: "handle", handle }— a handle you have reserved for one of your payees (a leading@is tolerated and stripped).{ kind: "email", email }— an email address.{ kind: "organization", handle }— an organization by its handle.{ kind: "payee", id }— a saved payee by id.
A bare EVM address (0x + 40 hex characters) is rejected by design with an
INVALID_INPUT error — the SDK and the backend both enforce it. The one lane
that accepts a raw address is
useCapxulWithdraw. The
TargetReference union also has a destination variant, but pay rejects it
with NOT_IMPLEMENTED — use
useCapxulPayout for saved
destinations.
actor. Only the personal actor can pay in the current alpha. Passing an
organization actor fails with NOT_IMPLEMENTED (payments.pay.organizationActor).
See Capability status.
timing. Omitted means instant — the direct-send path. A
{ kind: "scheduled", at } or { kind: "stream", startsAt, endsAt, cliffAt? }
clause turns the payment into a Commitment: an escrowed, cancellable,
redirectable payment that the recipient claims as it vests. Timestamps are
epoch milliseconds. Commitment payments enter the ledger as scheduled,
streaming, or pending_claim instead of pending.
The instant-send guardrail
An instant, irreversible payment is only permitted to a validated recipient. Paying anyone not yet validated always goes through a recoverable Commitment (escrowed, cancellable, redirectable). The SDK enforces this; it is not a bug to work around. See Capability status.
document and lineItems. An attached document (for example an invoice)
is hashed, stored, and committed with the payment; the returned Payment
carries only a document reference. The backend enforces the bindings: an
attached invoice's amount due must equal the amount being paid, paymentType
(when given) must match the document kind, and lineItems are accepted only
with an invoice document whose committed line-items hash and total they
reproduce exactly.
Return type
import { type UseCapxulPayReturn } from "@capxul/sdk-react";
// UseMutationResult<Payment, CapxulError, PaymentsPayInput>On success, data is the recorded Payment: its id, status, amount, the
recipient's kind and label, attached document references, the timing clause,
and the released / availableToClaim amounts for commitments.
The hook returns TanStack Query's UseMutationResult. The most-used fields:
| Field | Description |
|---|---|
mutate | Fire the mutation (fire-and-forget; pair with onSuccess/onError callbacks). |
mutateAsync | Fire the mutation and get a Promise of the result. Rejects with a CapxulError on failure. |
data | The mutation result (typed per hook, shown above). undefined until the first success. |
error | A CapxulError when the last attempt failed, otherwise null. |
isPending | true while the mutation is in flight. Use it to disable submit buttons. |
reset | Clear the mutation state (data, error) back to idle. |
Mutations do not retry by default. The full field list is in the
TanStack Query useMutation reference;
see also the TanStack Query integration guide.
Cache behavior
On success this mutation refreshes the personal money state: the payments list (and payment detail queries under it), the personal account balance, the personal insights summary and history, and the personal address book (paying someone new records them as a counterparty).
Errors
Failures surface as a CapxulError on error /
thrown from mutateAsync. Notable modes: INVALID_INPUT for a raw 0x
address, an empty or unresolvable recipient (unknown handle, payee, or org
handle), or an invoice document that disagrees with the amount or line items;
NOT_IMPLEMENTED for an organization actor or a destination target.
Client method
This hook wraps client.payments.pay(input) on the core SDK.