Agent API

Launch and mint over HTTP

An agent can launch and mint over HTTP. Registry reads are free. Priced endpoints answer an unpaid request with HTTP 402 and the payment requirements; the agent signs an EIP-3009 authorization, retries with it, and the platform relays the settlement and the onchain call. Payment is USDG on Robinhood Chain testnet, or USDC on Base when the deployment accepts it.

Chain 46630USDG settlementTestnet

01 / Addresses

This deployment

API base
https://ripples-api.onrender.com
Chain id
46630
USDG
0x11c6C3F8a6E9Aba45DaB68AfC1B0BA970794A77d
NFT factory
0x812AD1E01bF4a303aE5FF2CDFe74F920aeeBa88c
Reputation registry
0xa691dd0F06999233D56F2B397C41Cd7542c74aED

Contract addresses per deployment are recorded in contracts/deployments.json in the repository. The token factory address is not published here because an agent never calls it directly: the API returns every address a launch produces.

02 / Reads

Registry reads

Free, no headers.

curl
curl https://ripples-api.onrender.com/healthz
curl https://ripples-api.onrender.com/v1/collections
curl https://ripples-api.onrender.com/v1/collections/$COLLECTION
curl https://ripples-api.onrender.com/v1/launches
curl https://ripples-api.onrender.com/v1/launches/$TOKEN_OR_CURVE
curl https://ripples-api.onrender.com/v1/curve/$CURVE

/v1/launches/:address accepts the token, the curve, or the LP locker address of a launch and returns all three plus live curve state. The token endpoints answer 501 token_rail_not_configured on a deployment that runs the NFT rail alone.

03 / Payment

Paying: the 402 handshake

Send the request without payment first. The 402 body carries an accepts array; each entry names the network, the asset, the payTo address, and maxAmountRequired in the asset's smallest unit. USDG and USDC both use 6 decimals, so 5 USDG is 5000000. Read the amount and the payee from the challenge rather than hardcoding them: the launch fee is a deployment setting and a mint is priced from the collection.

Sign an EIP-3009 authorization over this domain:

EIP-712 domain
{
  "name": "Global Dollar",
  "version": "1",
  "chainId": 46630,
  "verifyingContract": "0x11c6C3F8a6E9Aba45DaB68AfC1B0BA970794A77d"
}

On Base the domain is USDC's own: name USD Coin, version 2, chain id 8453, and the USDC address from the challenge.

The message fields are the same for both authorization types: from, to, value, validAfter, validBefore, nonce (a random 32-byte value). Which type you sign depends on who moves the money:

EndpointprimaryTypepayTo
POST /v1/collectionsTransferWithAuthorizationplatform launch address, from the challenge
POST /v1/launchesTransferWithAuthorizationplatform launch address, from the challenge
POST /v1/collections/:address/mintTransferWithAuthorizationthe collection itself on chain 46630, the platform Base wallet on Base
POST /v1/curve/:curve/buyReceiveWithAuthorizationthe curve itself (home chain only)

The launch and mint paths are relayed: the platform submits transferWithAuthorization on your behalf, so the authorization has to be transferable by a third party. The curve pulls its own payment inside buyWithAuthorization, which requires the receive form so nobody else can redirect it.

Retry with the authorization base64-encoded in an X-PAYMENT header:

X-PAYMENT header
X-PAYMENT: base64(JSON({
  "x402Version": 1,
  "scheme": "exact",
  "network": "eip155:46630",
  "payload": {
    "authorization": { "from", "to", "value", "validAfter", "validBefore", "nonce" },
    "signature": "0x..."
  }
}))

Values are decimal strings, the nonce is 0x-prefixed 32 bytes, and the signature is the 65-byte EIP-712 signature. An authorization is single use: a replay answers 402 payment_reused, and one already spent on chain answers 402 authorization_spent. A settlement that moves no funds is refused.

04 / Collections

Launch an NFT collection

priceUSDG is the per-token mint price in micros. mode is PREGEN (the art is generated at launch) or LIVE (each mint triggers its own generation and reveal, which needs a placeholderURI).

A PREGEN brief generates inline, so brief.count is required and capped at 50. Omit it and the request is quoted for the whole maxSupply, which fails with 400 above the cap. Generate larger sets with the generator CLI and publish them with a baseURI.

POST /v1/collections · PREGEN
curl -X POST https://ripples-api.onrender.com/v1/collections \
  -H 'content-type: application/json' \
  -d '{
    "name": "Example",
    "symbol": "EXMPL",
    "priceUSDG": "5000000",
    "maxSupply": "1000",
    "providerId": "grok",
    "brief": { "prompt": "A short description of the art to generate", "count": 8 }
  }'

A LIVE drop takes no count: every mint generates one piece against the stored brief.

POST /v1/collections · LIVE
curl -X POST https://ripples-api.onrender.com/v1/collections \
  -H 'content-type: application/json' \
  -d '{
    "name": "Example Live",
    "symbol": "EXLIV",
    "priceUSDG": "5000000",
    "maxSupply": "1000",
    "mode": "LIVE",
    "placeholderURI": "ipfs://placeholder.json",
    "providerId": "grok",
    "brief": { "prompt": "A short description of the art to generate" }
  }'

Optional fields: perWalletCap, startTime, endTime (unix seconds, 0 for no limit), royaltyBps, baseURI. The creator recorded onchain is the address that paid. The response carries the collection address, the settle and launch transaction hashes, and an explorer link.

05 / Mint

Mint from a collection

Priced from the collection's onchain PRICE_USDG times qty, 1 to 20 per request. to is optional and defaults to the payer. On chain 46630 the payment settles directly to the collection, then the platform relays the mint.

POST /v1/collections/:address/mint
curl -X POST https://ripples-api.onrender.com/v1/collections/$COLLECTION/mint \
  -H 'content-type: application/json' \
  -d '{ "to": "0x0000000000000000000000000000000000000001", "qty": 1 }'

The response lists the minted token ids. A LIVE collection returns the placeholder URI until the reveal worker writes the finished piece, so poll tokenURI or isRevealed on the collection.

06 / Tokens

Launch a token

A token launch deploys the token, its bonding curve, and an LP locker. name and symbol are the only required fields; the curve parameters below have defaults that clear the factory's seed price band, and every one of them can be overridden with a decimal string.

POST /v1/launches
curl -X POST https://ripples-api.onrender.com/v1/launches \
  -H 'content-type: application/json' \
  -d '{ "name": "Example Agent", "symbol": "EXA" }'
FieldDefaultMeaning
curveSupply800000000e18Tokens sold on the curve
lpTokenSupply265000000e18Tokens seeded into the pool at graduation
vUsdgInit30000000000Virtual USDG reserve, micros
vTokenInit1073000000e18Virtual token reserve
graduationUsdg24000000000Real USDG that triggers graduation, micros
tradeFeeBps100Curve trade fee
poolFee3000Uniswap v4 pool fee
tickSpacing60Uniswap v4 tick spacing
lpUnlockAt0Unix second the LP position unlocks, 0 for locked

A linked launch pairs the token with a collection under one identity. Send token, nft (the collection fields above), and linked. Mint revenue routes a share to the curve, and a slice of the token supply vests to the collection's holders.

POST /v1/launches · linked
curl -X POST https://ripples-api.onrender.com/v1/launches \
  -H 'content-type: application/json' \
  -d '{
    "token": { "name": "Example Agent", "symbol": "EXA" },
    "nft": {
      "name": "Example Membership",
      "symbol": "EXMEM",
      "priceUSDG": "25000000",
      "maxSupply": "10000",
      "mode": "LIVE",
      "placeholderURI": "ipfs://placeholder.json"
    },
    "linked": {
      "nftAllocationBps": "500",
      "mintToCurveBps": "2000",
      "vestDuration": "31536000",
      "vestCliff": "2592000"
    },
    "providerId": "grok",
    "brief": { "prompt": "A short description of the art to generate" }
  }'

linked defaults to the values shown. The response adds the collection and vesting addresses to the token, curve, and locker.

07 / Curve

Buy on a bonding curve

usdgIn is the USDG to spend in micros, gross of the curve's trade fee. minTokensOut is required; pass "0" to accept any output, or quote first with quoteBuy on the curve and set a slippage bound. This endpoint settles on the home chain only.

POST /v1/curve/:curve/buy
curl -X POST https://ripples-api.onrender.com/v1/curve/$CURVE/buy \
  -H 'content-type: application/json' \
  -d '{ "usdgIn": "10000000", "minTokensOut": "0" }'

The curve verifies the authorization itself, so a rejected buy answers 402 buy_rejected with the onchain reason and nothing is spent. The response reports tokensOut and the buy transaction hash. Selling back to the curve and trading a graduated pool are onchain calls, not API endpoints.

Once a curve reaches graduationUsdg the keeper seeds the Uniswap v4 pool, locks the LP position, and closes curve trading. GET /v1/curve/:curve reports graduated and graduationReady throughout.

08 / Accounts

Account endpoints

/v1/me, /v1/me/launches, /v1/me/collections and /v1/me/drafts read what one signed-in person created. They take a Privy access token as a bearer credential and serve the web interface. An agent's launches are attributed onchain to the address that paid.

Ripples keeps the human interface and the agent API on the same contracts.