REST API
Parcl exposes a validator API for live chain state and a REST API for hosted authentication, signing, indexed history, and explorer data.
Environments
| Environment | Validator API | REST API |
|---|---|---|
| Mainnet | https://validator.v4.parcl.co | https://api.v4.parcl.co |
| Devnet | https://v4-api.dev.parcllabs.com | https://v4-rest-api.dev.parcllabs.com |
The validator WebSocket uses /v1/ws on the selected validator host. Pin the expected chain ID before signing.
All responses are JSON unless an endpoint states otherwise. Prices use 8 decimals, sizes use 6, and USDC amounts use 6.
Naming and integer formats
Most validator responses use camel case, such as marketId and oraclePrice. GET /v1/fee-tiers, GET /v1/node/info, recent trades, and WebSocket events use snake case because they mirror protocol or event shapes.
Large integers can be decimal strings. Treat account balances, volumes, prices, sizes, and counters as arbitrary-precision integers before applying their scale.
Markets
GET /v1/markets
Returns the active markets for the selected environment. Paused markets and markets in settlement do not appear in this list. Query GET /v1/markets/{id} to inspect a known market in another state.
curl https://v4-api.dev.parcllabs.com/v1/marketsThe response is an array. Each element has this shape:
[
{
"marketId": 0,
"name": "NYC",
"status": "Active",
"markPrice": "58177000000",
"bestBid": "58100000000",
"bestAsk": "58200000000",
"oraclePrice": "58035000000",
"oracleStatus": "Active",
"fundingRate": "-15800",
"openInterestLong": "37460000",
"openInterestShort": "37460000",
"maxOpenInterest": "1400000000",
"initialMarginRatioBps": 1000,
"maintenanceMarginRatioBps": 500,
"backstopAccountId": 5,
"feeTiersEndpoint": "/v1/fee-tiers",
"lastOraclePrice": "58035000000",
"lastOracleTimestamp": 1712345678000,
"oracleValidUntil": 1712433900,
"tickSize": "1000000",
"lastFundingTimestamp": 1712345678,
"fundingIntervalSecs": 3600,
"assetClass": "RealEstate",
"priceBandBps": 1000,
"interestRateMicroBps": 64,
"depthThresholdLamports": "25000000000",
"marginTiers": [
{
"notionalFloor": "0",
"maxLeverage": 10,
"maintenanceMarginRatioBps": 500,
"maintenanceDeduction": "0"
},
{
"notionalFloor": "500000000000",
"maxLeverage": 5,
"maintenanceMarginRatioBps": 1000,
"maintenanceDeduction": "25000000000"
}
]
}
]bestBid and bestAsk can be null when that side of the order book is empty.
feeTiersEndpoint is a discovery link to the canonical fee schedule. The market object does not include a fee rate because the rate also depends on account volume. backstopAccountId identifies the account that receives positions during a backstop liquidation, so a client can follow the resulting transfers. marginTiers is ordered by notionalFloor; a flat schedule has one row at floor zero. See markets and margin.
GET /v1/markets/{id}
Returns one market with the same shape.
GET /v1/markets/{id}/orderbook
{
"marketId": 0,
"bids": [{ "price": "58100000000", "size": "500000", "orderCount": 1 }],
"asks": [{ "price": "58200000000", "size": "300000", "orderCount": 1 }]
}GET /v1/markets/{id}/funding
Returns the current funding state for one market:
{
"marketId": 0,
"fundingRate": "69183",
"cumulativeFunding": "2388785636613712714",
"lastFundingTimestamp": 1779819896651,
"fundingIntervalSecs": 3600,
"maxFundingRateBps": 625
}fundingRate is the running estimate for the next hourly settlement. cumulativeFunding is the per-market index that positions settle against. See funding.
GET /v1/markets/{id}/trades
Returns recent public fills. The response is an array and uses snake-case event fields:
[
{
"price": "68391000000",
"size": "30000000",
"side": "Long",
"timestamp": 1787486431524,
"taker_order_id": 219262738,
"maker_order_id": 219262368,
"tx_hash": "5b977ba3304f5f9c..."
}
]Accounts
GET /v1/accounts/{id}
Returns collateral, positions, open orders, volume, and account policy fields:
{
"accountId": 12,
"owner": "0x35504e68...",
"mode": "Cross",
"collateral": "21929491932",
"positions": [
{
"marketId": 0,
"side": "Long",
"size": "64560188",
"entryPrice": "58211606845",
"unrealizedPnl": "-120297107",
"cumulativeFunding": "0",
"lastOraclePrice": "58090000000",
"openedAt": 1712345678000,
"margin_mode": "Cross",
"leverage": 50,
"isolated_margin": "0",
"tierGrandfathered": false
}
],
"openOrders": [],
"createdAt": 1712300000000,
"volume30d": 37581522814,
"feeTierVolume30d": 37581522814,
"lifetimeVolume": 142581522814,
"pendingActivation": false
}prclBalance is the account's liquid PRCL balance as a decimal string in base units.
availableCollateral is the amount of USDC available to transfer, also as a
base-unit decimal string. It accounts for positions and open orders. Both tokens
use six decimal places. PRCL is excluded from collateral and account equity.
pendingActivationFeeUsdc appears on an account that is awaiting its first qualifying deposit. agents appears when the account has approved agent keys.
GET /v1/accounts/by-owner/{pubkey}
Finds the personal account for a Parcl Chain public key. The key can include or omit the 0x prefix.
GET /v1/accounts/by-owner/{pubkey}/assets
Returns the owner's accounts, including subaccounts and managed vault accounts.
This public read does not require authentication. An invalid public key returns
HTTP 400. An owner without accounts receives an empty accounts array.
| Field | Meaning |
|---|---|
accounts[].accountId | Account ID |
accounts[].masterAccountId | Parent ID for a subaccount; null for a root |
accounts[].isVault | True for a vault root |
accounts[].collateral | Account USDC balance |
accounts[].availableCollateral | USDC available to transfer after margin reservations |
accounts[].prclBalance | Liquid PRCL held by that account |
accounts[].positionCount | Number of open positions |
accounts[].openOrderCount | Number of open orders |
unallocatedPrcl | PRCL awaiting assignment to a personal Master |
stakedPrcl | Owner's delegated PRCL, separate from liquid account balances |
unbondingPrcl | Owner's unbonding PRCL, separate from liquid account balances |
accounts[].balances lists each asset's tokenId, symbol, decimals,
total, available, and collateralEligible. unallocated lists token IDs and
amounts awaiting personal Master. The named USDC/PRCL fields remain compatibility
projections. Generic amounts are decimal strings in base units. Use each token's
decimals to format them; USDC and PRCL both use six. Parse amounts as integers. Do not add staking holdings to each subaccount: they
belong to the owner and their liquid entry and exit account is personal Master.
The staking balance endpoint reports funds available from Master, or unallocated
funds before Master exists. It does not sum spendable PRCL across subaccounts.
GET /v1/tokens
Public registry read. tokens contains id, symbol, name, and decimals.
Use the ID to select an asset; symbols do not define identity. representations
lists approved sources and their deposit/withdrawal flags. capabilities reports
genericTransfers and atomicSubaccountClosure. Check these before submitting
those actions.
GET /v1/transfers/recipient
Authenticated recipient lookup. Query kind is username, wallet, or account;
value is the corresponding name, public key, or account ID. Wallet lookup accepts
a Solana base58 public key or a 32-byte hexadecimal owner key. It resolves the
personal Master for that key. Username lookup resolves the user's personal Master.
An account ID selects that specific personal account.
Returns accountId, masterAccountId, owner, and isMaster. IDs are decimal
strings. Invalid input returns 400; a missing or ineligible recipient returns 404.
GET /v1/transfers/history
Authenticated transfer history for the owner. Returns up to 50 items and a
nullable nextCursor. Pass that cursor as ?cursor=... for the next page.
Each item has blockHeight, eventIndex, timestamp, txHash, fromAccountId,
toAccountId, fromOwner, toOwner, tokenId, amount, reason, and direction.
amount is a base-unit decimal string. IDs are decimal strings. reason is
Transfer or SubaccountClose; direction is incoming, outgoing, or own.
Own-account transfers appear once. History remains available after closure and
starts with the generic transfer release. Invalid cursors return 400.
GET /v1/accounts/{id}/positions
Returns the positions array.
GET /v1/accounts/{id}/orders
Returns the open-orders array.
GET /v1/accounts/{id}/rate-limit
Returns the account's on-chain request budget and congestion quota. See request limits.
GET /v1/bridge/state?owner={owner}
Returns bridge state. The optional owner query adds two fields for that owner:
| Field | Meaning |
|---|---|
owner | The requested public key as 64 lowercase hex characters |
unclaimed_usdc | Attested USDC awaiting account creation, as a base-unit decimal string |
The query does not require an existing account. An owner with no unclaimed
funding returns "0". A malformed owner key returns HTTP 400. Without the query,
the response omits these two fields.
Use /v1/accounts/by-owner/{owner}/list to check for a personal account.
Use /v1/node/info to verify the chain ID and /v1/treasury-config to read
account_activation_fee_usdc. See funded account creation.
GET /v1/accounts/{id}/invites
Returns invitation eligibility and usage for the account.
| Field | Description |
|---|---|
accountId | Account ID |
eligible | Whether the account can refer new users |
allowance | Total invitation allowance |
consumed | Invitations used |
remaining | Invitations available |
lifetimeVolume | Account lifetime trading volume |
inviteOverride | Account-specific allowance, or null |
nextUnlockVolume | Null; invitations do not require trading volume |
Oracle
GET /v1/oracle/{market_id}
Returns the current price, update date, timestamps, validity window, and Active, Stale, or Halted status.
{
"marketId": 0,
"price": "58035000000",
"lastUpdateTimestamp": 1712345678000,
"lastUpdateDate": 20260406,
"status": "Active",
"validUntil": 1712433900
}GET /v1/oracle/{market_id}/history
Returns historical oracle points. time is Unix seconds. price uses 8 decimals. Real estate markets publish one point per day.
{
"marketId": 0,
"prices": [
{ "time": 1748217600, "price": "59738000000" },
{ "time": 1748304000, "price": "59855999999" }
]
}Exchange configuration
GET /v1/fee-tiers
Returns the effective trading-fee schedule. Filter tiers to the market's
assetClass, then choose the highest min_volume_30d at or below the account's
feeTierVolume30d, the trailing 30-day volume of the account's family. A
negative maker fee is a rebate. See the canonical fee table.
GET /v1/treasury-config
Returns the live account-activation, subaccount-capacity, vault-capacity, and open-order-cap settings. Amount and volume fields use scaled integer strings. The selected environment's response is authoritative; do not hard-code these values.
GET /v1/node/info
Returns protocol_version, binary_version, build_sha, block_height, block_timestamp, state_root, and chain_id. The binary and block fields change as the chain advances. Validate their shapes and pin only the expected chain_id: parcl-v4:mainnet:chain-1 for mainnet or parcl-v4:devnet:chain-2 for devnet.
Bridge state
GET /v1/bridge/state
Returns transfer availability, the withdrawal window, pending totals, token limits, and current limit usage. Amounts inside limits are decimal strings in each token's smallest unit.
The rolling response also includes each direction's current *_used value.
These counters change with bridge activity. See
Solana bridge for transfer stages and direct deposits.
Transactions
POST /tx/sign-and-submit
Host: REST API. Accepts an authenticated owner browser session or X-API-Key.
The request contains one transaction, a millisecond nonce, and a seconds timestamp. The hosted signer signs and forwards it after the applicable owner-session or API-key checks. See transactions for exact bodies and authentication for API-key variants.
POST /v1/tx
Host: validator API. Agent-key clients submit a direct signed envelope. The
signature covers the UTF-8 bytes of
JSON.stringify([chainId, transaction, nonce, timestamp]) using the exact
submitted transaction bytes. See
transactions for the contract.
Indexed account history
These REST API endpoints require an owner session or API key and return only owned-account data:
| Endpoint | Result |
|---|---|
GET /v1/accounts/{id}/trades | Fill history |
GET /v1/accounts/{id}/trades/csv | Fill history as CSV |
GET /v1/accounts/{id}/orders | Order history |
GET /v1/accounts/{id}/funding | Funding-payment history |
The JSON endpoints accept limit, offset, startTime, endTime, and marketId where applicable. Monetary values are scaled integer strings. The CSV endpoint returns all rows matching its filters.
Statistics
GET /v1/stats on the REST API returns aggregate exchange counts and volumes. Statistics are indexed data and can lag validator state.