For agent developers

Every shop here is an API.

Every Awning business is born agent-payable: listed the minute it opens, offers as JSON, and an x402 checkout that pays the owner’s wallet in USDC on Base. Use the PayBox plugin, or call the API and pay the 402 yourself.

RIDGE ROASTx402 v2
  1. POST /x402/b/ridge-roast/250-g-coffee-bag
  2. 402 Payment RequiredPAYMENT-REQUIRED: base64 terms
  3. amount 14000000 (14.00 USDC)
  4. payTo the owner’s wallet
  5. network eip155:8453, scheme exact
  6. PayBox: one approval by a person
  7. POST same URL + PAYMENT-SIGNATURE
  8. 200 OK{order, receipt: {tx, payer, payTo}, fulfillment}
TO THE OWNER
AWNING’S CUT 0.00
14.00

Nine tools in the PayBox plugin.

A standard MCP server (protocol 2026-07-28) running in PayBox’s sandbox. Strict schemas in and out, 4 s timeouts, money as decimal strings plus atomic USDC. The two paying tools only return proposals; PayBox asks a person to approve.

  • awning_aboutread

    What Awning is, what it costs and how to use the tools. The conformance sample call.

    in
    {}
    out
    {name, version, summary, apiHost, payments: {chain, asset, symbol}, tools: [{name, use, cost}], flows: {open[], buy[], manage[]}}
    calls
    none
  • awning_planfree

    Turns one sentence into a draft business, domain options and a price. Creates a private draft; no money.

    in
    {sentence (8-600 chars), ownerWallet (0x + 40 hex), ownerName?, ownerEmail?, country?}
    out
    {planId, expiresAt, previewUrl, business: {slug, name, tagline, description, category, city, palette, offers[]}, domains: [{domain, available, domainPriceUsd, openPriceUsd}], packages: [{id, label, includes[], priceUsd}]}
    calls
    POST /v1/plan
  • awning_open_freefree

    Opens the plan on name.awning.sh at no cost.

    in
    {planId}
    out
    {business: {slug, name, url, status}, ownerToken}
    calls
    POST /v1/open-free
  • awning_openpays

    Registers the domain, buys the line and goes live. Returns an x402 proposal for PayBox; never pays by itself.

    in
    {planId, domain, priceUsd}
    out
    {"io.paybox/transactionProposal": {kind: "x402", chain: "eip155:8453", request: {url: ".../x402/open/<planId>", method: "POST", body: {domain, package: "pro"}}, payment: {asset, maxAmount}}}
    calls
    GET /v1/plans/:planId, unpaid POST /x402/open/:planId (quote)
  • awning_findread

    Searches every open business and offer.

    in
    {query?, category?, limit? (1-25, default 10)}
    out
    {count, businesses: [{slug, name, tagline, description, category, city, url, phone, domain, status, openedAt, salesCount, offers: [{sku, title, description, priceUsd, priceAtomicUsdc, kind}]}]}
    calls
    GET /v1/businesses?q=&category=&limit=
  • awning_businessread

    One business: offers, prices, phone.

    in
    {slug}
    out
    {business: {...same shape as one awning_find entry}}
    calls
    GET /v1/businesses/:slug
  • awning_buypays

    Buys an offer. The proposal pays the owner's wallet directly, price x qty.

    in
    {slug, sku, qty? (1-100, default 1), buyerNote?, buyerContact?}
    out
    x402 proposal: POST .../x402/b/<slug>/<sku> with {qty, buyerNote?, buyerContact?}, maxAmount = price x qty (atomic USDC)
    calls
    GET /v1/businesses/:slug, unpaid POST /x402/b/:slug/:sku (quote)
  • awning_add_offerowner

    Adds an offer to a live site; buyable at once.

    in
    {slug, ownerToken, title, description, priceUsd, kind: product|service|booking|digital|subscription}
    out
    {slug, added, offers[]}
    calls
    POST /v1/businesses/:slug/offers
  • awning_ordersowner

    The owner's orders, with receipts.

    in
    {slug, ownerToken}
    out
    {slug, count, totalUsd, orders: [{id, sku, qty, totalUsd, status, createdAt, tx, payer, buyerNote, buyerContact}]}
    calls
    GET /v1/orders?slug=

Buy from an agent, in one call.

  1. discover_plugins finds Awning for “coffee in Accra”, “bike repair”, “book a class”.
  2. get_contract returns the tool schemas above.
  3. use_plugin calls awning_buy. The result is a PayBox request: a person approves it with one tap.
  4. Poll the request. The paid response carries the order, the receipt and the transaction on Base. Do not call the tool again: a second approval is a second order.
use_plugin
{
  "plugin_id": "<your Awning installation id>",
  "tool_id": "awning_buy",
  "input": {
    "slug": "ridge-roast",
    "sku": "250-g-coffee-bag",
    "qty": 1,
    "buyerNote": "Saturday, 10:00"
  },
  "wallet_id": "<only if you have more than one wallet>"
}

Ridge Roast is a real Awning business: this call buys “250 g Coffee Bag” for 14.00 USDC. PayBox picks the wallet; Awning never sees its id.

Two x402 endpoints.

USDC on Base (eip155:8453, asset 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913), scheme exact. Both also answer GET with the same 402 quote.

POST /x402/b/:slug/:sku

Buy an offer. Pays the business owner’s own wallet.

Body
{qty? (1-100), buyerNote?, buyerContact?} (or ?qty=)
Price
offer price x qty
payTo
the owner’s wallet (non-custodial)
Paid, 200
{order: {id, slug, sku, qty, totalUsd, status: "paid"}, receipt: {tx, payer, payTo, network, settlement}, fulfillment: {kind, message, code?, url?}}
Refused
409 business_not_open, 403 business_suspended (before any 402)

POST /x402/open/:planId

Open a plan on its own domain with a phone line (Pro).

Body
{domain?, package?: "pro"} (domain defaults to the plan’s recommendation)
Price
the plan’s quoted total for that domain (domain + first month)
payTo
Awning’s treasury
Paid, 200
{business: {slug, name, url, domain, phone, status: "live"}, ownerToken, receipts: {paidUsd, tx, payer}, steps: [{name, status, ms}]}
Refused
409 already_open, 410 quote_expired, 503 pro_unavailable
  • Unpaid request → 402 with PAYMENT-REQUIRED (base64 JSON, x402Version: 2, accepts[{scheme, network, amount, asset, payTo, maxTimeoutSeconds: 300}]). The body repeats the terms in the v1 form plus a readable awning quote.
  • Paid retry: PAYMENT-SIGNATURE (v2) or X-PAYMENT (v1), an EIP-3009 transferWithAuthorization for exactly the quoted amount and payTo. The answer carries PAYMENT-RESPONSE.
  • Idempotent: the authorization is the key. The same signed payment twice returns the same order, byte for byte; a concurrent duplicate gets 409 payment_in_progress.

The public API.

JSON, CORS-open, no key. Base URL https://api.awning.sh. Plan, open and owner endpoints need the brokered x-awning-plugin-key header that PayBox adds, so use them through the plugin.

curl -s "https://api.awning.sh/v1/businesses?q=coffee&limit=5"
Find businesses and offers
curl -s https://api.awning.sh/v1/businesses/ridge-roast
One business, with buy links and payTo
curl -si -X POST https://api.awning.sh/x402/b/ridge-roast/250-g-coffee-bag -H 'content-type: application/json' -d '{"qty":1}'
Get the quote (402, no side effects)
curl -s "https://api.awning.sh/v1/live?limit=20"
Every opening and sale, newest first
EndpointReturns
GET /v1/businesses?q=&category=&limit={businesses: [{slug, name, tagline, category, city, url, phone?, offers: [{sku, title, priceUsd, kind}], openedAt, salesCount}]}
GET /v1/businesses/:slug{business: {..., palette, offers: [{..., buyUrl}], payTo, status, package}} (410 while under review)
GET /v1/businesses/:slug/offers{offers}
GET /v1/live{events: [{type: "opened"|"order"|"call", at, slug, name, amountUsd?, tx?}]}
GET /v1/health{ok, version, lastOpenAt, lastOrderAt, checks, facilitator, adapters}

What the API promises.

  • A quote is only a quote. Unpaid requests never write, provision or call a provider.
  • Pay only on success. Work happens first, settlement after. If the work fails, the authorization is never settled; a failure found after settlement is refunded from the treasury in the same response, with the refund transaction.
  • Owners are paid directly. Sales settle to the business’s own wallet. Awning takes no cut and never holds customer money.
  • One approval per payment. No standing permissions: every open and every purchase waits for a person in PayBox.
  • Reports pause checkout. A business under review answers 410 and refuses to quote. Report a business.