DEV Community

Cover image for Building a checkout for AI agents with x402 and MPP
Grov.fun
Grov.fun

Posted on Fully Autonomous

Building a checkout for AI agents with x402 and MPP

We built Grov, a paid social growth storefront for people and AI agents. Human buyers browse a catalog and use a checkout. Agents use an HTTP API and pay in USDC through x402 or MPP, without creating a Grov account or requesting a Grov API key.

The useful engineering question is broader than our product: how do you sell something to software that can choose a service, authorize a payment, and come back for the result?

Here is the request flow we use, including a quote you can inspect without spending anything.

1. Make the catalog readable before asking for payment

An agent needs more than an endpoint URL. It needs the service identifier, required input, quantity limits, and a way to understand the response.

We generate our storefront and agent discovery documents from the same catalog. This keeps the available services and their limits consistent across the two interfaces.

You can inspect the public catalog and usage instructions:

curl -fsS https://grov.fun/skill.md
Enter fullscreen mode Exit fullscreen mode

There is also an OpenAPI document for clients that prefer a structured interface description. Treat catalog prices as discovery information. The live payment challenge is the quote to evaluate before paying.

2. Ask for a quote with an ordinary HTTP request

This example requests a quote for 50 paid likes on one of our own public demo posts:

curl -i --get 'https://grov.fun/api/base/xlikes' \
  --data-urlencode 'url=https://x.com/grovdotfun/status/2098556423139455038' \
  --data-urlencode 'amount=50'
Enter fullscreen mode Exit fullscreen mode

Without a payment credential, the expected response is HTTP 402 Payment Required. This command does not pay or place an order.

For x402, the response describes the accepted payment scheme, network, token, amount, and recipient. The client should inspect those requirements before signing anything. It still needs a funded wallet and authorization to spend. “No API key” does not mean “no payment credentials.”

3. Use the payment client for the protocol you selected

Both protocols use a challenge and a paid retry, but their headers are different:

x402 MPP
Initial response HTTP 402 HTTP 402
Challenge header PAYMENT-REQUIRED WWW-Authenticate: Payment ...
Paid retry header PAYMENT-SIGNATURE Authorization: Payment ...

For x402, a payment-aware client such as @x402/fetch can handle the challenge and retry. For MPP, use a client matching the selected payment method. Our API documentation includes examples for both.

Before allowing a paid retry, check the recipient, network, currency, and amount against the user's instructions and spending limit. Never construct a new payment just because a previous request timed out. First establish whether that payment succeeded.

4. Separate payment from delivery

A successful payment creates an order. It does not mean the work is complete.

Our order response includes an orderId, a private secret, and a statusUrl. Save these immediately. The secret is the credential for reading that order, so it belongs in private agent state, not a public log or a conversation screenshot.

A later status request is free. For example, after an order has been created:

curl --get 'https://grov.fun/api/base/xlikes' \
  --data-urlencode 'action=view' \
  -H 'X-Secret: YOUR_ORDER_SECRET'
Enter fullscreen mode Exit fullscreen mode

Delivery progresses separately from checkout. Agents need to distinguish “paid and queued” from “completed,” and keep checking the existing order instead of purchasing again while work is still in progress.

What we want feedback on

The pattern is: discover the service, inspect the live quote, authorize the payment, save the receipt and access token, then track the result.

We are the team behind Grov. If you are building agents that buy services, what would you need before trusting this flow in production: clearer spending controls, better receipts, a sandbox, or something else?

Top comments (0)