How access works

Overview

HoodPortal is a REST layer over Robinhood Chain. It manages wallets, executes trades, and launches tokens on Pons — so you can automate all three from a backend instead of a browser wallet.

There are no API keys. Every write request is signed by the wallet performing the action, and HoodPortal checks that wallet's live $PORTAL balance before it executes anything — hold at least 1,000 $PORTAL, or the request is rejected. See Access for the exact mechanics.

Base URL — all examples below assume https://api.hoodportal.xyz/v1.

Access

No API keys. Access is tied to the wallet signing each request, not to an account or a plan.

Every write request (POST) must be signed by the wallet performing the action. HoodPortal recovers the signer from that signature, confirms it matches the wallet you're claiming to act as, and reads that wallet's live $PORTAL balance on-chain before doing anything else.

RequirementDetail
Minimum balance1,000 $PORTAL, held by the signing wallet at the moment the request is processed.
Applies toAll POST endpoints — wallets, trades, launches, webhooks.
Does not apply toGET endpoints. Price, quote, and token lookups are open with no balance or signature required.
Signature freshnessThe signed timestamp must be within 60 seconds of the request. Older signatures are rejected.

Signing a request

Sign the message hoodportal:{timestamp}:{sha256(body)} with the wallet's private key, then attach the result as headers:

headersEvery POST request
X-Wallet-Address: 0x4dd2...9a71
X-Wallet-Signature: 0x9c1f...02ad
X-Timestamp: 1725556800
Keep your private key server-side. It's what proves you control the wallet and what HoodPortal checks the $PORTAL balance against. Never ship it in a client-side app.
Balance is checked live, not cached. If a wallet's $PORTAL balance drops below 1,000 between one request and the next, later requests fail with insufficient_portal_balance until it's topped back up.

Wallets

Create sub-wallets under one account and issue scoped session keys for each.

POST/wallets

Creates a new wallet. Funds must be deposited to its address before it can trade, and it needs at least 1,000 $PORTAL before it can sign any further request.

FieldTypeRequiredDescription
labelstringrequiredA name for your own reference. Not shown on-chain.
requestPOST /v1/wallets
{ "label": "sniper-03" }

// 200 OK
{
  "wallet_id": "wl_8f2ac1",
  "address": "0x4dd2...9a71",
  "status": "ready"
}

POST/wallets/:id/session-keys

Issues a scoped session key for a wallet. HoodPortal uses this key to execute trades and launches on the wallet's behalf — it can never exceed the scope you set here, and it stops working the moment the wallet's $PORTAL balance drops below 1,000, regardless of expiry.

FieldTypeRequiredDescription
spend_cap_ethnumberrequiredMaximum ETH the key can move, in total, over its lifetime.
daily_cap_ethnumberoptionalResets every 24h. Omit for no daily limit below the spend cap.
expires_instringrequiredDuration string, e.g. "30d". Max 90d per key.
allowed_contractsstring[]optionalRestrict to specific contracts. Omit to allow any Pons curve or Uniswap v4 pool.
requestPOST /v1/wallets/wl_8f2ac1/session-keys
{
  "spend_cap_eth": 2.0,
  "daily_cap_eth": 0.5,
  "expires_in": "30d"
}

// 200 OK
{ "session_key_id": "sk_9d41", "expires_at": "2026-10-05T00:00:00Z" }

GET/wallets/:id

Returns balances across every token the wallet holds, plus its active session keys. No signature or $PORTAL balance required to read.

Trading

Buy or sell any Robinhood Chain token. HoodPortal reads the token's phase and routes the order to its Pons curve or its Uniswap v4 pool automatically.

POST/trades/buy

FieldTypeRequiredDescription
wallet_idstringrequiredThe wallet executing the trade. Must hold at least 1,000 $PORTAL.
tokenaddressrequiredToken contract address.
amount_ethnumberrequiredAmount to spend, in the token's quote asset.
slippage_bpsintegeroptionalMax acceptable slippage, in basis points. Defaults to 200 (2%).
requestPOST /v1/trades/buy
{
  "wallet_id": "wl_8f2ac1",
  "token": "0x39dBED3a2bd333467115dE45665cC57F813C4571",
  "amount_eth": 0.05,
  "slippage_bps": 200
}

// 200 OK
{
  "status": "confirmed",
  "venue": "curve",
  "tx_hash": "0x7ad3f1...e02c",
  "tokens_out": "142893.221",
  "price_usd": 0.000041
}

POST/trades/sell

Same shape, in reverse — pass a token amount instead of an ETH amount.

requestPOST /v1/trades/sell
{
  "wallet_id": "wl_8f2ac1",
  "token": "0x39dBED3a2bd333467115dE45665cC57F813C4571",
  "amount_tokens": "50000",
  "slippage_bps": 200
}

GET/tokens/:address

Live price, market cap, phase (curve or graduated pool), and graduation progress for any token on the chain. No signature or balance required.

responseGET /v1/tokens/0x39dB...4571
{
  "phase": "curve",
  "price_usd": 0.000041,
  "market_cap_usd": 41000,
  "graduation_progress": 0.71
}

Launching on Pons

Deploy a new token and, optionally, buy your own opening allocation — atomically, so nothing can trade in between.

POST/launches

FieldTypeRequiredDescription
wallet_idstringrequiredWallet that deploys the launch and receives creator fees. Must hold at least 1,000 $PORTAL.
name / symbolstringrequiredToken name and ticker.
quote_assetstringoptional"ETH" by default. See Pons docs for approved alternatives.
creator_tax_bpsintegeroptionalYour own tax on top of the standard fee. Capped by the protocol.
initial_buy_ethnumberoptionalIf set, buys your opening allocation in the same transaction as the launch.
requestPOST /v1/launches
{
  "wallet_id": "wl_8f2ac1",
  "name": "Sherwood",
  "symbol": "SHRWD",
  "quote_asset": "ETH",
  "creator_tax_bps": 100,
  "initial_buy_eth": 0.05
}

// 200 OK
{
  "status": "launched",
  "token": "0x2fe1...a04b",
  "curve": "0x88ab...11de",
  "tx_hash": "0x51ac...90fd"
}
Creator tax is fixed at launch. It can't be raised later, on this endpoint or anywhere else — matching how the tax works directly on Pons.

Webhooks

Subscribe to an event instead of polling for it.

EventFires when
trade.confirmedA buy or sell you submitted lands on-chain.
launch.graduatedA token you launched sells out its curve and moves to its Uniswap v4 pool.
rewards.claimableA weekly $PORTAL creator-rewards payout becomes available to claim.
requestPOST /v1/webhooks
{
  "url": "https://yourapp.com/hooks/hoodportal",
  "events": ["trade.confirmed", "launch.graduated"]
}

Errors

Errors return a 4xx or 5xx status with a machine-readable code.

CodeStatusMeaning
insufficient_portal_balance403The signing wallet holds less than 1,000 $PORTAL. Top up and retry.
invalid_signature401The signature doesn't recover to the claimed wallet address, or the timestamp is stale.
slippage_exceeded422Price moved past your slippage_bps before the trade settled.
session_key_expired401The wallet's session key has expired or was revoked. Issue a new one.
spend_cap_exceeded403The request would exceed the session key's remaining spend cap.
curve_graduated409The token finished its curve between your quote and your trade. Retry — HoodPortal will route to the pool.
insufficient_balance402The wallet doesn't hold enough of the quote asset.

$PORTAL & rewards

$PORTAL gates access and funds creator rewards. There is no fee tier, no subscription, and no metering.

The access requirement

RequirementDetail
Minimum balance1,000 $PORTAL in the signing wallet, checked live on every write request.
CostNone. It's a balance check, not a fee — the tokens aren't spent or transferred to use the API.
ReadsGET endpoints are open to everyone, no balance required.

Creator rewards

Launching through POST /v1/launches instead of directly through Pons adds a second, ongoing reward stream on top of your normal Pons creator fees:

  1. Your token trades — on the curve, then in its graduated pool.
  2. Pons pays your standard creator share directly, in the launch's quote asset, exactly as it would without HoodPortal involved.
  3. Every HoodPortal launch also carries a small built-in 0.5% protocol fee, separate from Pons' own, pooled weekly.
  4. Half of that pool is paid out weekly, in $PORTAL, to the wallet that launched the token — for as long as it keeps trading.
responseGET /v1/wallets/wl_8f2ac1/rewards
{
  "token": "0x2fe1...a04b",
  "week_ending": "2026-09-06",
  "volume_usd": 184200,
  "portal_reward": "412.6 PORTAL",
  "claimable": true
}
This is usage-based, not speculative. A launch with no trading volume earns no $PORTAL rewards — the mechanic pays out a share of real fee revenue, not newly minted supply.