Skip to content

Payout ​

What it is ​

A Payout lets an agent send USDC from the user's FluxA Wallet to any external address on Base. Common use cases include withdrawals, revenue splits, paying contractors, refunds, and settling off-chain obligations.

Payouts support two approval paths:

  • Standard flow — the agent initiates, the user approves in the FluxA Wallet UI, and FluxA sends the transfer.
  • Mandate auto-approval — if the agent passes a pre-signed mandateId with sufficient budget, the payout is approved immediately with no user action.

What agents can do with it ​

  • Send funds to any address — initiate outbound USDC transfers to any 0x address on Base.
  • Auto-approve with mandates — pass a mandateId to skip user approval when the mandate covers the amount.
  • Deduplicate by business ID — pass a bizId so the same external order can never create two active payouts.
  • Track payout status — poll the status endpoint until the payout is completed or failed (see Reading the status).
  • Attach metadata — include custom metadata (order IDs, source labels) for reconciliation.
  • Webhook notifications — provide a webhook URL to receive push notifications on completion.
  • Idempotent retries — reuse the same payoutId to safely retry without duplicate transfers.
MethodEndpointDescription
POST/api/payoutsCreate a payout request
GET/api/payouts/:payoutIdGet payout status

User-side actions (approve / deny a pending payout) are performed by the user directly in the FluxA Wallet UI via the approvalUrl returned at creation; there is no public API for them.

Integration flows ​

There are two flows depending on whether the agent has a pre-signed budget mandate.

Flow A — with a budget mandate (auto-approval) ​

Use this when the agent should send payouts autonomously within a user-approved budget (e.g. recurring refunds, revenue splits, task rewards). The payout skips manual user approval and starts processing immediately.

text
** Your task **
Send 2.00 USDC to 0xABCD...1234 as a reward for task #42.

** Step 1 — Create a budget mandate (once, reused across payouts) **
If the agent does not already have a signed mandate that covers this
kind of payout, create one and have the user sign it:

curl -X POST https://walletapi.fluxapay.xyz/api/mandates/create-intent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_JWT" \
  -d '{
    "intent": {
      "naturalLanguage": "Pay data labeling task rewards",
      "currency": "USDC",
      "limitAmount": "100000000",
      "validForSeconds": 2592000,
      "category": "task-reward"
    }
  }'

The response returns:
- mandateId (e.g. "mnd_abc12345")
- authorizationUrl — surface to the user so they can sign in the
  FluxA Wallet. The mandate is not usable until signed.

Poll the mandate until status is "signed":
  curl https://walletapi.fluxapay.xyz/api/mandates/agent/mnd_abc12345 \
    -H "Authorization: Bearer $AGENT_JWT"

** Step 2 — Create the payout with mandateId **
Pass the signed mandateId; the payout auto-approves atomically if
the remaining budget covers the amount:

curl -X POST https://walletapi.fluxapay.xyz/api/payouts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_JWT" \
  -d '{
    "payoutId": "reward-task-42",
    "toAddress": "0xABCD...1234",
    "amount": "2000000",
    "mandateId": "mnd_abc12345",
    "bizId": "task_42_reward",
    "description": "Data labeling reward — task #42"
  }'

Expected response:
- approvalUrl: null  (already approved, no user interaction)
- mandateId: "mnd_abc12345"

If the mandate budget is insufficient, the call fails with
`mandate_insufficient_budget`; fall back to Flow B or top up the
mandate.

** Step 3 — Poll for completion **
curl https://walletapi.fluxapay.xyz/api/payouts/reward-task-42 \
  -H "Authorization: Bearer $AGENT_JWT"

Read displayStatus. Keep polling while it is "processing" or
"awaiting_approval". It is done when "completed", and was not
sent when "failed", "expired", "rejected" or "canceled".

** Step 4 — Confirm **
- If completed: "Payout of 2.00 USDC sent. Tx: {txHash}"
- If failed: tell the user the payout was not sent and offer to
  try again with a new payoutId

Flow B — without a mandate (user manual approval) ​

Use this for ad-hoc or high-value transfers where the user should review each payout individually.

text
** Your task **
Send 2.00 USDC to 0xABCD...1234 as a one-off withdrawal.

** Step 1 — Create the payout (no mandateId) **
curl -X POST https://walletapi.fluxapay.xyz/api/payouts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_JWT" \
  -d '{
    "payoutId": "withdraw-001",
    "toAddress": "0xABCD...1234",
    "amount": "2000000",
    "bizId": "withdraw_001",
    "description": "User withdrawal"
  }'

Expected response:
- approvalUrl: "https://agentwallet.fluxapay.xyz/authorize-payout/..."
  (the payout waits for the user's approval)

** Step 2 — Ask the user to approve **
Surface the approvalUrl to the user. They open it in a browser and
approve (or deny) inside the FluxA Wallet. If they deny it, or the
approval window passes, the payout fails and nothing is sent.

** Step 3 — Poll for completion **
curl https://walletapi.fluxapay.xyz/api/payouts/withdraw-001 \
  -H "Authorization: Bearer $AGENT_JWT"

Read displayStatus. Keep polling while it is "processing" or
"awaiting_approval". It is done when "completed", and was not
sent when "failed", "expired", "rejected" or "canceled".

** Step 4 — Confirm **
- If completed: "Payout of 2.00 USDC sent. Tx: {txHash}"
- If failed: explain that the payout was not sent and offer to retry

Choosing between the flows ​

  • Flow A (mandate) — agent has a user-signed budget covering this payout. No user interaction; the payout starts processing immediately.
  • Flow B (manual) — ad-hoc or high-value transfers. The user must approve each payout via approvalUrl before anything is sent.

See Mandates for how to propose, sign, and query mandates.

Reading the status ​

Read displayStatus from GET /api/payouts/:payoutId:

displayStatusWhat to do
awaiting_approvalRemind the user of the approvalUrl
processingKeep polling. Don't create a second payout
completedDone. txHash is the on-chain transaction
failed, expired, rejected, canceledNothing was sent. Tell the user; create a new payout if they still want to send

Treat any other value as processing. Don't build logic on the lower-level status field; its values can change.

Using bizId for deduplication ​

When bizId is set, only one active payout can exist per user per bizId. This protects against accidental double-payment on retries. The bizId becomes available again once its payout has failed. While a payout is still processing, the bizId stays reserved.

With the CLI ​

bash
# Standard: the user approves via approvalUrl
fluxa-wallet payout --to 0xABCD...1234 --amount 2000000 --id withdraw-001 --biz-id withdraw_001

# Within a signed mandate: no separate approval
fluxa-wallet payout --to 0xABCD...1234 --amount 2000000 --id reward-task-42 --mandate mnd_abc12345

fluxa-wallet payout-status --id withdraw-001

See CLI › Payouts.

Released under the MIT License.