Skip to content

Unify Payment Link (UPL)

Resolve an agent's permanent receiving endpoint and pay via the x402 protocol. No wallet address lookup required — only the target Agent ID.


Get UPL

Request the 402 payment requirement for a target agent. The response tells you where to send funds and how much.

bash
curl -s "https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/<agentId>?amount=<atomic_units>&asset=usdc"

Path parameters

ParameterTypeDescription
agentIdstringThe recipient agent's agent_id (required)

Query parameters

ParameterTypeDescription
amountstringAmount in atomic units (required). 1 USDC = 1000000
assetstringAsset identifier (required). Only usdc is supported

Example request

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

Response (HTTP 402)

The server returns HTTP 402 with a JSON body following the x402 protocol format:

json
{
  "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": "0x1234567890abcdef1234567890abcdef12345678",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "extra": {
        "name": "USD Coin",
        "version": "2"
      }
    }
  ]
}
FieldDescription
x402VersionProtocol version (always 1)
accepts[].schemePayment scheme (exact)
accepts[].networkBlockchain network (base)
accepts[].maxAmountRequiredAmount to pay in atomic units
accepts[].resourceThe full UPL URL (use this as-is for the retry)
accepts[].descriptionHuman-readable description
accepts[].payToRecipient's current onchain wallet address
accepts[].assetUSDC contract address on Base
accepts[].extra.nameToken name (USD Coin)
accepts[].extra.versionToken version (2) — used for EIP-3009 signing

Error responses

StatusMeaning
400Missing amount or asset, invalid amount format, zero or negative amount, or unsupported asset
404Agent not found, agent has been deleted, or agent has no wallet linked

Error body:

json
{
  "error": "Agent not found",
  "code": "AGENT_NOT_FOUND"
}

Submit payment

After obtaining the 402 payload and signing the payment via POST /api/payment/x402V3Payment, retry the same UPL URL with the X-Payment header.

bash
curl -H "X-Payment: <xPaymentB64>" \
  "https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/<agentId>?amount=<atomic_units>&asset=usdc"

Headers

HeaderDescription
X-PaymentBase64-encoded payment proof from x402V3Payment (required)

Example request

bash
curl -H "X-Payment: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW..." \
  "https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/bob-agent-id?amount=2000000&asset=usdc"

Response (HTTP 200)

json
{
  "success": true,
  "txHash": "0xabc123...",
  "settledAmount": "2000000",
  "network": "base",
  "payer": "0x...",
  "payee": "0x..."
}
FieldDescription
successtrue if the onchain transfer succeeded
txHashTransaction hash on Base — use a block explorer to verify
settledAmountAmount transferred in atomic units
networkNetwork where the transfer was executed
payerSender's onchain address
payeeRecipient's onchain address

Error responses

StatusMeaning
400Invalid or malformed X-Payment header
402Payment proof is missing, expired, or insufficient
404Agent not found
500Onchain transfer failed (e.g., insufficient USDC balance in the sender's wallet)

End-to-end example

Complete flow from constructing the URL to receiving a confirmed transfer.

1. Get the 402 payload

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

PAYLOAD=$(curl -s "$UPL_URL")
echo "$PAYLOAD"
# → HTTP 402 with x402 JSON body

2. Create and sign a mandate

bash
curl -X POST https://walletapi.fluxapay.xyz/api/mandates/create-intent \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_JWT" \
  -d '{
    "intent": {
      "naturalLanguage": "Transfer USDC to agents via Unify Payment Link",
      "currency": "USDC",
      "limitAmount": "10000000",
      "validForSeconds": 2592000,
      "category": "upl-transfer",
      "hostAllowlist": ["walletapi.fluxapay.xyz"]
    }
  }'

Response:

json
{
  "status": "ok",
  "mandateId": "mnd_xyz789",
  "authorizationUrl": "https://agentwallet.fluxapay.xyz/mandate/mnd_xyz789",
  "expiresAt": "2025-03-01T00:00:00.000Z",
  "agentStatus": "ready"
}

Present authorizationUrl to the user. After they sign, verify the mandate status:

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

Confirm status is "signed" and isEnabled is true.

3. Sign the payment

Use the fields from the 402 payload (step 1) together with the mandate ID:

bash
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": "1000000",
    "currency": "USDC",
    "assetAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0x1234567890abcdef1234567890abcdef12345678",
    "host": "walletapi.fluxapay.xyz",
    "resource": "https://walletapi.fluxapay.xyz/unifypaymentlink/agentid/bob-agent-id?amount=1000000&asset=usdc",
    "description": "UPL transfer 1.00 USDC to bob-agent-id",
    "tokenName": "USD Coin",
    "tokenVersion": "2",
    "validityWindowSeconds": 60
  }'

Response:

json
{
  "status": "ok",
  "xPaymentB64": "<base64-encoded-xPayment>",
  "paymentRecordId": "..."
}

4. Submit and confirm

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

Response:

json
{
  "success": true,
  "txHash": "0xabc123...",
  "settledAmount": "1000000",
  "network": "base",
  "payer": "0x...",
  "payee": "0x..."
}

The transfer is confirmed onchain. Use the txHash to verify on a Base block explorer.


Notes

  • Atomic units — all amounts are in USDC atomic units (6 decimals). 1000000 = 1.00 USDC.
  • Mandate host — UPL endpoints are served from walletapi.fluxapay.xyz. Include this host in your mandate's hostAllowlist, or omit the allowlist entirely.
  • Payment validity — the xPaymentB64 token expires based on validityWindowSeconds (default 60s). Submit it promptly after signing.
  • Idempotency — if the same signed payment is submitted twice, the second request will be rejected. Generate a new payment proof for each transfer.

Released under the MIT License.