Create a payment
Create a personal-Account payment for a validated recipient and understand its current completion boundary.
client.payments.pay accepts product-level Money and a validated recipient. The
personal Account path prepares one stored UserOperation, validates the sender,
asks the configured wallet to sign one digest, and submits through the backend.
A successful result confirms that the backend recorded the submitted hash. It
does not claim final chain settlement.
Limited availability
Payment execution requires an environment with active CapxulPaymentsV2 writes. Use
client.org(orgId).payments for Organization payments. Check capability status before treating a
submitted Payment as settled.
Before you start
Create a client with the Account readiness your application requires, then
authenticate the user. This guide assumes you already have an initialized
client; see Choose Account readiness if you are
unsure which requirement to use.
Create the payment
Parse form text against the selected Account before submit:
import { formatMoney, parseMoney } from "@capxul/sdk";
const account = await client.accounts.read();
if (!account.ok) throw account.error;
const amount = parseMoney(formAmount, account.value.available);
if ("kind" in amount) {
showFieldError(copyFor(amount.reason)); // app-owned lookup (ADR-0023)
return;
}
console.log(formatMoney(amount, { grammar: "code" }));parseMoney uses the selected Account decimal count. It returns a validation
error value for missing, malformed, zero, negative, oversized, or over-precise
input.
formatMoney accepts any {currency, value, decimals} record, so it also
formats the money an activity row carries, whose currency is a plain string.
An unsupported currency code fails with INVALID_INPUT.
PAYMENT_STATUSES and PAYMENT_DIRECTIONS are the closed code vocabularies
themselves. Render a dropdown from them and keep the wording in the
application; the SDK ships no label for a code.
Pass the parsed Money and a validated recipient:
const paid = await client.payments.pay({
to: { kind: "email", email: "vendor@example.com" },
amount,
paymentType: "invoice",
});
if (!paid.ok) {
console.error(paid.error.code, paid.error.message);
return;
}
console.log(paid.value.id, paid.value.status);The personal path accepts handles, emails, Organizations, and saved payees—not
a raw wallet address. The paymentType value records the business purpose of
the payment.
Interpret the result
paid.ok means the SDK accepted the request and returned a payment record. Read
the record's status; do not reinterpret the presence of an ID as final
settlement.
Read the latest record when your UI needs to refresh its state:
const payment = await client.payments.get(paid.value.id);
if (!payment.ok) throw payment.error;
console.log(payment.value.status);Know the unavailable paths
- An Organization actor passed to
payments.payreturnsNOT_IMPLEMENTED. - A
destinationtarget passed topayments.payreturnsNOT_IMPLEMENTED. client.payments.cancelreturnsNOT_IMPLEMENTED; payment cancellation is not available.
See SDK capability status for the current availability summary and the method reference for exact evidence.