Skip to content

Unify Payment Link (UPL)

TIP

UPL is built on the x402 payment protocol. For full x402 details — including payment schemes, payload formats, and facilitator setup — see the x402 Protocol section.

What it is

A Unify Payment Link (UPL) is a permanent, public receiving endpoint that every agent gets out-of-the-box. Any sender who knows the target Agent ID can construct a UPL URL to send any amount of USDC to that agent — no wallet address required.

Every agent's UPL base address:

https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/<agentId>

This base address is permanent. You can save it, share it, and reuse it for future payments. Append amount parameters when you are ready to pay.

Why use UPL

  • No wallet address needed — only the target Agent ID is required. If the recipient agent changes its wallet address in the future, the UPL resolves to the new address automatically.
  • No gas fees for the sender — the payment goes through the x402 protocol (EIP-3009 TransferWithAuthorization), so the transfer is executed onchain by the protocol, not by the sender.
  • Works across wallets — any agent or user with a FluxA Wallet and a signed mandate can pay through a UPL.
  • Permanent endpoint — unlike a payment link (pl_*) that can be deleted or expired, the UPL base URL is tied to the Agent ID and never changes.
FeatureUPLPayment Link
URL lifetimePermanent (tied to Agent ID)Can expire or be deleted
AmountSet by the sender at payment timeFixed by the creator
Who creates itAnyone — just needs the Agent IDThe recipient agent via API
Content deliveryNoYes (resourceContent)
Use caseAgent-to-agent transfers, tipping, ad-hoc paymentsSelling goods, collecting fees, invoices

How it works

UPL leverages the x402 payment protocol. When you request a UPL URL with amount parameters, the server returns an HTTP 402 response containing the agent's current wallet address and payment requirements. You then sign an EIP-3009 TransferWithAuthorization via FluxA Wallet and submit the signed payload back — the USDC transfer is executed onchain by the protocol.

Sender                           FluxA Server                    Onchain
  |                                 |                               |
  |-- GET UPL?amount=&asset= ------>|                               |
  |<-- 402 {payTo, amount, ...} ----|                               |
  |                                 |                               |
  |-- sign via FluxA Wallet ------->|                               |
  |-- GET UPL + X-Payment -------->|-- execute transfer ---------->|
  |<-- 200 {receipt, txHash} ------|                               |

Detailed flow

  1. Construct the UPL URL with ?amount=<atomic_units>&asset=usdc.
  2. GET the URL — the server responds with HTTP 402 and a JSON payload describing the payment requirement (recipient address, amount, asset, network).
  3. Create a mandate (if you don't have one already) — call POST /api/mandates/create-intent to set a spending budget, then have your user sign it.
  4. Sign the payment — call POST /api/payment/x402V3Payment with your mandateId and the 402 payload fields. The server returns xPaymentB64.
  5. Submit the payment — retry the same UPL URL with the X-Payment: <xPaymentB64> header. The server verifies the signature, executes the onchain transfer, and returns a 200 with the transaction receipt.
MethodEndpointDescription
GET/unifypaymentlink/agentid/:agentIdGet 402 payment requirement for the target agent
GET/unifypaymentlink/agentid/:agentId + X-PaymentSubmit signed payment to complete the transfer
POST/api/mandates/create-intentCreate a spending mandate (budget + time window)
GET/api/mandates/agent/:mandateIdCheck mandate status and remaining budget
POST/api/payment/x402V3PaymentSign a payment using a mandate (returns xPaymentB64)

Integration flow

Below is an example prompt you can give an AI agent to send a USDC payment to another agent via UPL.

text
** Your task **
Send 2.00 USDC to agent "bob-agent-id" using a Unify Payment
Link (UPL). Use the x402 V3 mandate flow so payments are
autonomous within your budget.

** Step 1 — Construct the UPL URL **
The target agent's UPL endpoint:

UPL_URL="https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/bob-agent-id?amount=2000000&asset=usdc"

- amount is in atomic units: 2.00 USDC = 2000000
- asset must be "usdc"

** Step 2 — Get the 402 payment requirement **
curl -s "$UPL_URL"

The server returns HTTP 402 with a JSON body like:
{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "base",
    "maxAmountRequired": "2000000",
    "resource": "https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/bob-agent-id?amount=2000000&asset=usdc",
    "description": "Pay 2.00 USDC to bob-agent-id",
    "payTo": "0x...",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "extra": {
      "name": "USD Coin",
      "version": "2"
    }
  }]
}

Save the fields from the accepts[0] object — you will need
them for the payment call.

** Step 3 — Create and sign a mandate **
curl -X POST https://walletapi.fluxapay.xyz/api/mandates/create-intent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_JWT" \
  -d '{
    "intent": {
      "naturalLanguage": "Send USDC to other agents via UPL. Budget: 10.00 USDC over 30 days.",
      "currency": "USDC",
      "limitAmount": "10000000",
      "validForSeconds": 2592000,
      "category": "upl-transfer",
      "hostAllowlist": ["walletapi.fluxapay.xyz"]
    }
  }'

The response returns:
- mandateId  (e.g. "mnd_xyz789")
- authorizationUrl (short link, TTL 10 minutes)

Ask the user to open authorizationUrl and sign the mandate.
Then verify the mandate is signed:

curl https://walletapi.fluxapay.xyz/api/mandates/agent/mnd_xyz789 \
  -H "Authorization: Bearer $AGENT_JWT"

Confirm status is "signed" and isEnabled is true before
proceeding.

** Step 4 — Sign the payment via x402 V3 **
Using the 402 payload fields from Step 2 and your mandateId:

curl -X POST https://walletapi.fluxapay.xyz/api/payment/x402V3Payment \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_JWT" \
  -d '{
    "mandateId": "mnd_xyz789",
    "scheme": "exact",
    "network": "base",
    "amount": "2000000",
    "currency": "USDC",
    "assetAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "<payTo from 402 response>",
    "host": "walletapi.fluxapay.xyz",
    "resource": "https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/bob-agent-id?amount=2000000&asset=usdc",
    "description": "UPL transfer to bob-agent-id",
    "tokenName": "USD Coin",
    "tokenVersion": "2",
    "validityWindowSeconds": 60
  }'

The response includes xPaymentB64 — a base64-encoded signed
payment proof.

** Step 5 — Submit the payment **
Retry the UPL URL with the X-Payment header:

curl -H "X-Payment: <xPaymentB64>" "$UPL_URL"

A 200 response confirms the transfer was executed onchain.
The response body includes the transaction receipt and
txHash.

** Step 6 — Report **
Summarize to the user:
- Amount sent: 2.00 USDC
- Recipient: bob-agent-id
- Transaction hash
- Mandate remaining budget

Mandate planning for UPL

When using UPL, your mandate's hostAllowlist should include walletapi.fluxapay.xyz since all UPL endpoints are served from this host. A single mandate can cover transfers to multiple agents — the host is the same regardless of the target Agent ID.

Sizing your mandate budget

Consider how many UPL transfers you expect to make over the mandate's validity period:

ScenarioSuggested budgetValidity
Single one-off transfer of 5 USDC50000001 hour (3600)
Regular small transfers (tips, micro-payments)10000000 (10 USDC)30 days (2592000)
High-volume agent-to-agent settlement100000000 (100 USDC)30 days (2592000)

WARNING

Once a mandate's budget is exhausted or expires, you must create and sign a new one. Plan ahead to avoid payment failures mid-workflow.

Error handling

UPL endpoint errors

These errors occur when curling the UPL URL (before entering the x402 flow):

StatusMeaningAction
400Missing amount or asset, invalid amount, or unsupported assetCheck your query parameters
404Agent not found, deleted, or has no walletVerify the Agent ID is correct

x402 payment errors

These errors occur during the mandate / payment signing step:

StatusstatusMeaningAction
400mandate_requiredmandateId was not providedInclude a valid mandateId
403mandate_not_foundMandate does not exist or does not belong to this agentCheck mandate ID and ownership
403mandate_insufficient_budgetRemaining budget is less than the payment amountCreate a new mandate with sufficient budget
403agent_not_authorizedAgent is not authorized in the user's walletHave the user open authorizationUrl

See Error Codes for a full list of error codes.

Tips

  • Reuse mandates — a single mandate can pay many UPL transfers as long as the budget and time window are sufficient.
  • Check balance first — call GET /api/mandates/agent/:mandateId to see remainingAmount before attempting a large transfer.
  • Host allowlist — if your mandate includes a hostAllowlist, make sure walletapi.fluxapay.xyz is in the list. Omitting hostAllowlist allows any host.
  • Atomic units — always express amounts in atomic units. 1 USDC = 1000000 (6 decimals).

Released under the MIT License.