You can buy visits from people who use crypto and pay for them in USDC, from a wallet, without opening an account. This guide buys the smallest order there is, ten visits for $0.05, and then a larger one from a prepaid balance.
What you are buying
The traffic comes from two places: users of FaucetPay, who are paid to open your page and keep it open, and visitors of the publisher sites in the network, who see your ad next to what they came for.
| Format | What you get | Price |
|---|---|---|
| PTC (paid-to-click) | A person opens your page and keeps it open for 10 to 120 seconds | From $0.005 per click |
| Paid Visits | A rewarded visit of 5 to 120 seconds to your landing page | From $0.01 per completed visit |
| Banner and Native | Your ad on publisher sites; you bid per click or per thousand impressions | $5 minimum order |
PTC is the cheapest way to start: 1,000 clicks at the lowest bid cost $5.00, and an order can be as small as 10 clicks. The full list, with every limit, is on the ad formats page.
What you need
- A wallet holding USDC on Base, Polygon or Arbitrum. It needs no ETH: you sign a payment authorization and the gas is paid for you.
- An x402 client, which signs that authorization. There is one for every common language; the examples below use the JavaScript one.
- A landing page on
https.
Step 1: ask for the price
Nothing is created and nothing is charged by a quote.
curl -s https://cryptoadvertising.net/api/v1/quote \
-H 'content-type: application/json' \
-d '{"product":"PTC","name":"First order","landing_url":"https://example.com/",
"ad_title":"Have a look at this page",
"ad_description":"Open the page and look around for ten seconds.",
"product_options":{"clicks":10,"duration_seconds":10}}'
The answer names the total, "total_usd":"0.05", and how it is made up.
Step 2: place the order and pay
Send the same order to POST /api/v1/ads with an Idempotency-Key header (a
random UUID). The first answer is 402 Payment Required with the price in USDC
on each network. Your x402 client signs the payment and repeats the request; the
second answer is 201 with the ad and an API key.
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
// The order that was quoted in step 1.
const order = {
product: "PTC",
name: "First order",
landing_url: "https://example.com/",
ad_title: "Have a look at this page",
ad_description: "Open the page and look around for ten seconds.",
product_options: { clicks: 10, duration_seconds: 10 },
};
const pay = wrapFetchWithPaymentFromConfig(fetch, {
schemes: [{
network: "eip155:8453", // Base
client: new ExactEvmScheme(privateKeyToAccount(process.env.WALLET_PRIVATE_KEY)),
}],
});
const response = await pay("https://cryptoadvertising.net/api/v1/ads", {
method: "POST",
headers: { "content-type": "application/json", "idempotency-key": crypto.randomUUID() },
body: JSON.stringify(order),
});
const { ad, api_key } = await response.json();
Keep the API key. It is the account that owns the ad, it is shown once, and there is no email address to recover it with.
Step 3: follow the ad
Every ad is reviewed before it goes live, so its status starts as in_review.
curl -s https://cryptoadvertising.net/api/v1/ads/16 -H 'authorization: Bearer can_live_...'
GET /api/v1/ads/{id}/stats shows the clicks or visits delivered and what they
cost. An ad that is rejected in review returns its whole budget to the balance.
Buying more than once: prepaid credit
Paying for each order separately is fine for one. For several, buy credit first:
POST /api/v1/credits/25 costs 25 USDC and returns an API key holding $25.00.
Orders placed with that key are paid from the balance, with no payment exchange
at all, and what an ad does not spend comes back to it.
What it costs, and what it does not
- You pay the price the quote names. There is no fee on top and no minimum deposit; the only minimum is the order's own.
- The payment goes from your wallet straight to ours. We never hold your keys.
- A balance is not refunded to a wallet automatically. It stays usable; a refund is a manual transfer on request.
The complete reference is llms.txt for a language model and openapi.json for a program.