Trading Call Flow¶
This is the order to call the API in. Start from a managed account that has never traded and finish with a strategy placing real orders on Hyperliquid.
Open the diagram full screen ↗
Fund the account before you approve the agent
Hyperliquid will not accept an agent approval from an account with no equity. The API
reports that rejection as a plain 500, so it looks like a server fault when it is
really an empty account. Deposit first, confirm equity, then approve.
Orders are placed indirectly
There is no standalone place-order endpoint. Orders come from an armed advanced strategy or from a playlist action. If you want one ad-hoc order, put it in a playlist.
Binding details live on the Hyperliquid page
Which key signs what, agent naming rules, expiry limits and the full approval surface are on Hyperliquid Connection. This page only covers the order.
1. Pick the account¶
GET /api/managed-accounts
Save the id, the address (the Hyperliquid master address) and the customerId. Every
{id} below is that account id, and you need all three values in the steps that follow.
2. Check for an existing binding¶
GET /api/managed-accounts/hyperliquid-binding/accounts?customerId={customerId}
data: null means this customer has no binding yet and you can start at step 3. If an
account comes back, a binding already exists and may still be pending. Use that account for
the rest of the flow instead of binding a second one.
3. Resolve the deposit inputs¶
GET /api/configs
GET /api/assets?chainId={chain}&address={usdcAddress}
GET /api/venues?status=active&search=Hyperliquid
Start with /api/configs. It is an open read-only route, so no token is needed. Read the
chain list from it, pick a chain that supports deposits, and take that chain's USDC address
and its forwardFee. It has no entry in the API reference, which is why step 3 has no link
of its own.
Then /api/assets gives you the USDC id and decimals. The venue list is under
Venues ↗: take the item with
slug: "hyperliquid" and save its id as venueId.
4. Create the deposit playlist¶
POST /api/playlists
{
"accountId": "{id}",
"customerId": "{customerId}",
"name": "Deposit USDC to Hyperliquid perp",
"status": "active",
"strategyTemplateId": "hyperliquid_deposit",
"stopConditions": [
{
"scope": { "scope": "playlist" },
"type": "execution_count",
"config": { "maxExecutions": 1 },
"actionOnTrigger": "complete",
"enabled": true
}
],
"steps": [
{
"order": 1,
"stepType": "trigger",
"name": "Instant deposit request",
"type": "instant",
"config": { "type": "instant" },
"enabled": true
},
{
"order": 2,
"stepType": "action",
"action": "deposit",
"venue": "{venueId}",
"product": "hyperliquid-perp",
"assetId": "{assetId}",
"asset": "USDC",
"assetAddress": "{usdcAddress}",
"assetDecimals": 6,
"amount": "30000000",
"amountSource": { "type": "static", "unit": "token" },
"chain": "{chain}",
"params": { "source": "hyperliquid_deposit_sheet", "hyperCoreDestination": "perp" }
}
]
}
amount is in base units, not USDC. At 6 decimals, 30 USDC is "30000000". The amount also
has to clear the chain's forwardFee, which is deducted on arrival, so a deposit at or below
the fee lands as nothing.
Swap "perp" and "hyperliquid-perp" for "spot" and "hyperliquid-spot" if you are
funding the spot side.
5. Wait for the funds¶
GET /api/managed-accounts/{id}/hyperliquid/positions
Poll until equity is above zero. The money has to cross from the chain to Hyperliquid, so this is not instant. Do not move to step 6 on a zero balance.
6. Approve the agent¶
POST /api/managed-accounts/{id}/hyperliquid-binding/approve
{
"venueAccountAddress": "{account address}",
"agentName": "paros-agent",
"expiryDays": 30,
"isRevoke": false
}
Send expiryDays (1 to 180) or expiresAt, never both. agentName takes up to 16
characters: letters, digits, spaces, - and _.
Give this call at least 180 seconds
Approve blocks while the Salt signing ceremony runs and can take well over a minute. A client timeout of 60 seconds will fire on a call that is still working.
7. Confirm the binding¶
GET /api/managed-accounts/{id}/hyperliquid-binding/approval-status
Setup is complete when the response shows approved: true and agents[] holds the agent's
agentAddress. If approved is false and agents is empty, the binding is still pending:
re-check equity in step 5, then call approve again.
A 409 means do not retry approve
409 already in progress means your first approve call is still running. Retrying starts
a second signing ceremony. Poll this endpoint until it resolves.
8. Builder fee (optional)¶
POST /api/managed-accounts/{id}/hyperliquid-binding/builder-fee
{ "isRevoke": false }
Read it back with GET on the same path, which returns approved and maxFeeRate. This one
is master-signed, so it waits on custody like the approval did.
9. Read the market¶
GET /api/managed-accounts/{id}/hyperliquid/markets
GET /api/managed-accounts/{id}/hyperliquid/markets/{symbol}/state
Use symbol (for example "ETH") as the productId when you build the strategy. Market
state returns markPrice, funding and the numbers you need to set rule thresholds.
10. Create the strategy draft¶
POST /api/advanced-strategies
{
"accountId": "{id}",
"customerId": "{customerId}",
"name": "ETH funding carry",
"metadata": { "templateId": "funding_carry" },
"strategyClass": "generative",
"level": 2,
"setupConfig": {},
"setupProductId": "ETH",
"riskConfig": {
"maxLeverage": "4",
"maxDrawdownPct": "12",
"allowedVenueIds": [],
"deniedProductIds": []
},
"rules": [
{
"order": 1,
"name": "Enter carry",
"enabled": true,
"cooldownSeconds": 3600,
"conditions": [
{
"role": "trigger",
"key": "funding_rate",
"operator": "greater_than",
"order": 0,
"config": { "ratePctPerHour": "0.02", "productId": "ETH" }
}
],
"actions": [
{
"key": "place_order",
"order": 1,
"custodyGate": "agent",
"config": {
"productId": "ETH",
"side": "buy",
"notionalUsd": "20",
"orderType": "market",
"reduceOnly": false
}
}
]
}
]
}
A rule that contains place_order needs cooldownSeconds above zero. Actions inside one
rule are either all generative or all protective, and mixing the two is rejected. Leverage is
capped by riskConfig.maxLeverage.
To change a draft afterwards, PUT /api/advanced-strategies/{id}/draft with
{ "name"?, "metadata"?, "definition": { ...same fields... } }.
11. Validate¶
POST /api/advanced-strategies/{id}/validate
No body. If it returns issues, fix them through step 10 and validate again before you publish.
12. Publish¶
POST /api/advanced-strategies/{id}/publish
No body. A published strategy still does nothing; it has no permission to trade until you arm it.
13. Arm¶
POST /api/advanced-strategies/{id}/arm
{}
Pass { "versionId": "<uuid>" } to arm a specific version. Arming needs the binding from
step 7 to be approved: true. Once armed, the server evaluates your rules and places orders
through the agent.
To test the same rules without sending real orders, call
POST /api/advanced-strategies/{id}/dry-run instead of arming. It runs the same rules and
sends no orders.
When a step fails¶
| Symptom | Where it breaks | What to do |
|---|---|---|
500 from approve |
Step 6, account still unfunded | Check equity in step 5 and fund again |
409 from approve |
Step 6, a ceremony is already running | Poll step 7, do not call approve twice |
| Timeout on approve | Step 6, client gave up early | Raise the timeout to 180 seconds and poll step 7 |
approved: false, agents: [] |
Step 7, binding not finished | Re-check equity, then approve again |
| Arm refused | Step 13, binding not approved | Finish step 7 first |
| Validation issues | Step 11, bad rule shape | Fix the definition, PUT the draft, validate again |