open solid
← Guides

How an AI agent pays contractors

An AI agent can pay a person with one API call. On Open Solid, every payout is a POST /api/v1/pay from the agent's wallet with a type of venmo, paypal, debit or bank. The recipient gets the full amount and the fee is added on top. Every payout is checked against a per-payment spend limit the owner sets. Venmo and PayPal need the owner to verify their identity once. Bank payments go to recipients the owner registers in the dashboard.

Choosing a rail

Rail type Amount Fee Best for
Venmo venmo $5 to $1,000 4.9%, $1.50 minimum Small payments to people who use Venmo
PayPal paypal $5 to $1,000 4.9%, $1.50 minimum Freelancers who prefer PayPal
Debit card payout debit $10 to about $9,500 4.8%, $1.50 minimum Paying someone without knowing their account details
Bank payment (ACH) bank $10 to $50,000 0.25%, $1.50 minimum Larger or recurring invoices

Fees come from Laso Finance's live pricing, and the agent can read them before paying with GET /api/v1/pricing, which needs no auth. For anything above a few hundred dollars, ACH is far cheaper: a $1,200 invoice costs $3.00 by ACH, while a $1,000 Venmo payment costs $49.00.

Before the first payout

Three things need to be in place.

A funded wallet. Payouts come out of the agent's USDC balance. If the wallet can't cover the fee-inclusive total, /pay returns 402 and nothing is charged.

Identity verification for Venmo and PayPal. The account owner must be identity verified before the first Venmo or PayPal payout. The agent checks:

curl https://opensolid.ai/api/v1/kyc \
  -H "Authorization: Bearer $OPENSOLID_API_KEY"

If kyc_verified is false, the agent sends the owner the link in next and waits. It never fills in an identity form on the owner's behalf.

Bank recipients, for ACH. The owner adds each bank recipient in the dashboard: name, address, routing and account number. The agent never handles a contractor's bank details directly.

Finding recipients

The agent lists saved recipients for a rail with GET /api/v1/recipients, or the list_recipients MCP tool with the same rail argument:

curl "https://opensolid.ai/api/v1/recipients?rail=bank" \
  -H "Authorization: Bearer $OPENSOLID_API_KEY"

curl "https://opensolid.ai/api/v1/recipients?rail=venmo" \
  -H "Authorization: Bearer $OPENSOLID_API_KEY"

Bank recipients each have one or more destinations, and each destination has a destination_id, which is what /pay takes. Venmo and PayPal recipients are saved automatically the first time someone is paid, so the list grows as the agent works. Before paying someone new, the agent should check the list for an existing entry. That avoids sending money to a mistyped phone number or email.

Paying by Venmo

For Venmo, recipient_id is the recipient's 10-digit phone number.

curl -X POST https://opensolid.ai/api/v1/pay \
  -H "Authorization: Bearer $OPENSOLID_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2b9e-3d4a-4e8b-9c51-0a7d2e6f4b13" \
  -d '{
    "type": "venmo",
    "amount": 80,
    "recipient_id": "5551234567",
    "note": "Jordan Reyes, 4 product photos for the spring listing"
  }'

Paying by PayPal

For PayPal, recipient_id is the recipient's email, along with first_name and last_name.

curl -X POST https://opensolid.ai/api/v1/pay \
  -H "Authorization: Bearer $OPENSOLID_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "type": "paypal",
    "amount": 150,
    "recipient_id": "sam@example.com",
    "first_name": "Sam",
    "last_name": "Lee",
    "note": "Sam Lee, voiceover for launch video"
  }'

At 4.9%, this costs $157.35.

Paying by debit card

A debit payout returns a redemption link. The agent sends the link to the contractor, who opens it and enters their debit card, and the money arrives in minutes. currency is USD, EUR or GBP, so this rail also works for contractors paid in euros or pounds.

curl -X POST https://opensolid.ai/api/v1/pay \
  -H "Authorization: Bearer $OPENSOLID_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"type": "debit", "amount": 200, "currency": "USD", "note": "Priya Nair, illustration set for onboarding emails"}'

A $200 debit payout costs $209.60. Send the link only to the person it is for.

Paying by bank transfer

ACH takes a destination_id from the recipients list and normally settles in one to two business days.

curl -X POST https://opensolid.ai/api/v1/pay \
  -H "Authorization: Bearer $OPENSOLID_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"type": "bank", "amount": 1200, "destination_id": "dest_123", "note": "Dana Park, October video editing, invoice 14"}'

The spend limit is fee-inclusive

The owner sets the most any single payment can be, from $1 to $50,000, with a default of $1,000. The agent reads it with GET /api/v1/spend-limit and cannot change it.

The limit applies to the total including fees, not to the amount the recipient gets. A $1,000 Venmo payment costs $1,049, so it is refused under a $1,000 limit. A refused payment returns 403 with "terminal": true.

When that happens, the agent stops. It does not retry, switch rails, or split the payment into two smaller ones. It tells the owner who it wanted to pay, the fee-inclusive total and the current limit, and the owner decides. AI agent spending limits covers this rule in depth.

Idempotency: never pay a contractor twice

Retries are the usual cause of accidental double payouts. Send an Idempotency-Key header with every /pay call: a fresh UUID for each intended payment, stored before the request goes out and reused on every retry of that payment. MCP clients pass the same value as the idempotency_key argument to the pay tool.

A successful payment responds with:

{ "replayed": false, "result": { "...": "..." }, "activity": { "...": "..." }, "paid_usd": 157.35 }

paid_usd is the fee-inclusive amount that left the wallet. If the same key arrives again, the API does not pay twice. It returns the recorded payment with "replayed": true in the response body. There is no special header for this, so the agent must read the body.

After a timeout, the agent retries with the same key or checks GET /api/v1/activity. It never makes up a new key because a request failed.

Write a note on every payment

Every payout takes a note: one sentence on who was paid and what for. It appears next to the payment in the owner's activity feed and in /activity. Good notes name the person, the work and an invoice or task reference: "Dana Park, October video editing, invoice 14". Notes turn a weekly review into a skim. A vague note such as "payment" is itself a sign that something needs a closer look.

Next steps