Transfer Domain
transfer_domainSpends account credit, or pays directly by card (pay_with_card) or in USDC (pay_with_usdc). Initiates a transfer of an external domain into Porkbun.
Instructions
Spends account credit, or pays directly by card (pay_with_card) or in USDC (pay_with_usdc). Initiates a transfer of an external domain into Porkbun. Requires the auth/EPP code from the losing registrar, and cost_cents must match the current transfer price from check_domain. Poll with get_transfer_status. Most transfers finish well inside the five-day worst case — two thirds within 24 hours — so do not promise the user a week. .uk and a few TLDs do not support inbound API transfers. Idempotency-safe.
Set hold_for_dns_setup unless the user has no DNS to preserve. A transfer carries only the delegation, so a domain that moves before its records exist at Porkbun goes dark. Holding charges the transfer but parks it until you release it: hold → prepare_transfer → import_dns_records → start_transfer. Nothing releases a held transfer on a timer.
How a purchase is paid. From prepaid account credit by default; a card saved at Porkbun is never charged by a purchase itself. Or directly, for this one purchase: pay_with_card: true (the user's card from their Stripe Link agent wallet, held and charged only if the purchase succeeds) or pay_with_usdc: true (USDC on Base over x402). If the credit is short, the call fails with INSUFFICIENT_FUNDS carrying cost, balance, shortfall, topUpAvailable and usdcAmountToCover (dry_run: true reports the same without charging). Ways forward, simplest first, always telling the user the dollar amount and getting their OK: (1) if they use Stripe Link, retry this exact call with pay_with_card: true; (2) if you can pay x402 (a wallet tool, or this server has PORKBUN_X402_PRIVATE_KEY), retry with pay_with_usdc: true; (3) when topUpAvailable is true a card is saved: top_up_account_credit (amount_cents at least topUpAmountToCover, or omit it for their configured amount), then retry; (4) add credit with top_up_with_card_mpp (Link) or top_up_with_usdc (for usdcAmountToCover, which allows for Coinbase's ~1% fee), then retry; (5) the user adds credit at https://porkbun.com/account/credit. If a purchase fails with VERIFICATION_REQUIRED, the phone (send_phone_verification_code then confirm_phone_verification) and the email (send_email_verification_code then confirm_email_verification) can both be verified without leaving the conversation, the user reading out each code. Suggest configure_auto_topup if they want credit refilled automatically. Money parameters are integer cents: state amounts to the user in dollars (cost_cents: 1108 is $11.08). If you do not move money on a user's behalf, hand it back instead: tell them the shortfall and that they can add it with buy account credit at https://porkbun.com/account/credit, then retry once they have.
Buying for a new or unfunded account: the whole path, including what only the human can do, is at https://porkbun.com/llms/guides/buy-a-domain-from-an-agent. Paying directly in USDC (no account credit needed): set pay_with_usdc: true. If this server has a wallet configured (PORKBUN_X402_PRIVATE_KEY, local installs only), the payment is signed and the purchase completes in this one call. Otherwise the result is status: PAYMENT_REQUIRED with a checkoutId, an x402Url and a payUrl, and nothing is charged: pay the x402Url with a wallet tool that pays x402 URLs (for example Coinbase's awal x402 pay <x402Url> --scheme auth-capture), or have the user pay the payUrl page, then call this tool again with the same arguments plus usdc_checkout_id. Tell the user the dollar amount first. If the purchase fails after payment, the payment is NOT returned to the wallet: it stays on the Porkbun account as credit (the error says keptAsCredit: true with the new balance), so retry without pay_with_usdc to buy from that credit.
Paying directly by card, with a hold (no account credit needed): set pay_with_card: true when the user pays with Stripe Link. The result is status: PAYMENT_REQUIRED with a payUrl and a cardPaymentId; nothing is charged. Pay the payUrl with an MPP wallet tool. With Link's CLI that is two commands: link-cli mpp pay <payUrl> -X POST --context "..." (context at least 100 characters) creates a spend request the user approves in Link; once approved, complete it with link-cli mpp pay <payUrl> --spend-request-id <lsrq_id> -X POST. That only authorizes the card. If link-cli answers NOT_AUTHENTICATED, run link-cli auth login first (a one-time device login the user approves). Then call this tool again with the same arguments plus card_payment_id: if the purchase succeeds the card is charged, and if it fails the hold is released and nothing is charged. The link works until expiresAt; if that passes before it is paid, call this tool again without card_payment_id for a fresh link instead of paying the old one.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cost | No | Deprecated alias of `cost_cents`, same unit (integer US cents). Send `cost_cents` instead. | |
| domain | Yes | Domain to transfer in, e.g. `example.com` | |
| dry_run | No | If true, validate and preview (`dryRun: true`, `wouldSucceed`) WITHOUT initiating the transfer or charging. | |
| auth_code | Yes | Authorization (EPP) code from the losing registrar. | |
| cost_cents | No | Transfer price. Must match the value returned by `check_domain`. Required. Integer US cents: 803 means $8.03, not $803. | |
| pay_with_card | No | Pay for this purchase by card from the user's Stripe Link agent wallet (MPP), with a hold: charged only if the purchase succeeds. Tell the user the amount first. | |
| pay_with_usdc | No | Pay for this purchase directly in USDC on Base (x402) instead of from account credit. Tell the user the amount first. | |
| card_payment_id | No | The cardPaymentId from an earlier PAYMENT_REQUIRED (pay_with_card), once its payUrl has been paid. Send it with the same arguments as that call. | |
| usdc_checkout_id | No | The checkoutId from an earlier PAYMENT_REQUIRED result, once its x402Url or payUrl has been paid. Send it with the same arguments as that call. | |
| hold_for_dns_setup | No | Charge the transfer but hold it at PENDINGDNS instead of releasing it, so DNS can be set up before the domain moves. Not supported for .uk/Handshake (returns TRANSFER_HOLD_NOT_AVAILABLE and charges nothing). |