Integration guide
Use this page when you want exact integration steps. The hand-written API pages explain which surfaces exist and how they behave operationally. The GMX API OpenAPI reference is generated and is best used for endpoint schemas and response fields, not for workflow guidance. Use Troubleshooting when reads do not match expected state.
Choose the right integration surface
Start by choosing the narrowest surface that solves your problem.
| Need | Recommended surface | Notes |
|---|---|---|
| Live oracle prices, market snapshots, liquidity, and APY | Oracle API pages | Stable public HTTP endpoints on gmxinfra.io. Use GMX API /yield/gm-pools when fee APY and trader PnL must use the same pool and time window. |
| Read app-level HTTP data such as markets, tickers, JIT-aware trading capacity, tokens, pairs, rates, APY, GM-pool yield and trader PnL, performance, positions, orders, trades, OHLCV, wallet balances, allowances, buyback stats, JIT liquidity, risk-oracle market lists, staking power, USDG launch boost rates, deposit whitelists, or USDC and USDG conversion quotes | SDK v2, the generated GMX API reference, or direct GMX API HTTP calls | SDK v2 provides typed TypeScript helpers for its supported methods; use direct HTTP for routes not yet wrapped or generated |
| Protocol-wide volume, fees, revenue, TVL, open interest, users, and trades across networks and GMX versions | Direct GMX API GET /stats/summary, /stats/timeseries, and /stats/sources, or the SDK v2 fetchApiProtocolStats* functions | Chain-agnostic and computed only by the Arbitrum deployment. See Read protocol-wide stats. |
| LP fee earnings for one wallet's GM token holdings | GMX API GET /yield/gm-user-earnings or SDK v2 fetchGmUserEarnings() | Per chain and GM only. Use the GraphQL glvUserEarnings resolver for GLV vault earnings. See Read GM LP fee earnings for one account. |
| Historical trade and order activity | SDK v2, the generated GMX API reference, or GraphQL | Use GMX API or SDK v2 for API-backed trade reads; use GraphQL for full indexed history and custom analytics |
| Submit, edit, cancel, or track orders | SDK v2, SDK v1, or direct contract calls | SDK v2 posts signed order intents to the GMX API, which submits express orders through GMX Relay. SDK v1 and direct contracts remain available for RPC-owned flows |
| Submit already-built relay-router calldata and track the relay operation | Direct GMX API POST /relay/submit and POST /relay/status | Low-level, operation-agnostic GMX Relay surface. Persist its taskId; it doesn't replace the SDK v2 /orders/txns/* workflow. |
| Exchange or aggregator pair listings | Integration pair feed | Public GET endpoints at https://gmx-integration-cg.vercel.app/api/arbitrum/pairs and https://gmx-integration-cg.vercel.app/api/avalanche/pairs. For GMX on Solana, GET https://solana.gmxapi.io/v1/pairs returns the perpetual pairs in the GMX API /pairs format |
| Delegated, gasless, or one-click order flows on behalf of a user | Delegated trading integration | Subaccount and relay pattern using SubaccountGelatoRelayRouter and MultichainSubaccountRouter |
| GM or GLV token prices | Getting GM and GLV token prices | Explains when to use Chainlink Data Feeds, Reader calls, or API/SDK data for GM/GLV valuation |
What is available now
The current hand-written docs and checked-out code support the following split:
| Surface | Read | Write | Description |
|---|---|---|---|
| GMX API OpenAPI Reference | ✅ | ✅ | Generated schema reference for the GMX API. Covers markets, JIT-aware trading capacity, tokens, positions, orders, trades, rates, APY, GM-pool yield and trader PnL, GM LP fee earnings, protocol-wide stats, performance, JIT liquidity, wallet balances, allowances, staking power, buyback stats, USDG launch boost rates, deposit whitelists, USDC and USDG conversion through Paxos on Arbitrum, the GMX on Solana pair feed, GMX Account, subaccount approval/status, order transaction flows, and generic relay submission/status. Deployed per chain across two independent peer base URLs: https://{chain}.gmxapi.io/v1 and https://{chain}.gmxapi.ai/v1. |
Oracle API (gmxinfra.io) | ✅ | ❌ | Public market, price, liquidity, APY, and performance reads. Manual docs cover the stable public HTTP endpoints. |
| GraphQL | ✅ | ❌ | Historical indexed activity. Best for history, not write-path confirmation. |
SDK v1 (GmxSdk) | ✅ | ✅ | Full TypeScript integration with reads and writes. Uses RPC, oracle, and Subsquid connections directly. |
SDK v2 (GmxApiSdk) | ✅ | ✅ | TypeScript integration over HTTP against the GMX API. Reads, wallet helpers, subaccount helpers, and order-submission methods are available. |
| Direct contracts | ✅ | ✅ | Lowest-level integration and custom transaction flows. Highest control and highest implementation burden. |
Use the generated GMX API reference for endpoint-level request and response schemas. Use the SDK v2 docs for typed client method names, bigint parsing, signing helpers, and complete TypeScript workflows.
Build a live market overview
Use the Oracle API when you need public market snapshots and fallback URLs. Use /markets for a slower-changing market list, and /markets/info for a near-live market state snapshot.
const endpoints = [
"https://arbitrum-api.gmxinfra.io/markets/info",
"https://arbitrum-api-fallback.gmxinfra.io/markets/info",
"https://arbitrum-api-fallback.gmxinfra2.io/markets/info",
];
async function fetchMarketsInfo() {
let lastError: Error | undefined;
for (const endpoint of endpoints) {
try {
const response = await fetch(endpoint, {
headers: { Accept: "application/json" },
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
lastError = error as Error;
}
}
throw lastError ?? new Error("All market endpoints failed");
}
const markets = await fetchMarketsInfo();
console.log("Loaded markets:", markets.length);
Use this refresh strategy:
- Call
/marketswhen you need the market catalog and can tolerate a10second cache window. - Call
/markets/infowhen you need liquidity, open interest, funding, borrowing, token amounts, and theisListedflag. This is also the correct endpoint for near-live funding rates. - Treat
/markets/infoas a snapshot, not a guarantee of the latest block. The current implementation caches the route for10seconds, so build for near-live rather than same-block state. - Use
/markets/statewhen you only need each market's open, closed, or unknown status. This route is cached for5seconds. - Use
/ratesfor historical funding and borrowing rate data. This endpoint returns hourly snapshots from the Squid indexer, not realtime values. Use it for rate averages, trends, and historical analysis.
If you use the generated GMX API reference on https://{chain}.gmxapi.io/v1 or https://{chain}.gmxapi.ai/v1, the market reads are split by update frequency:
| Endpoint | Use when | Current cache window |
|---|---|---|
GET /markets | You need the listed market catalog, leverage tiers, and size limits. | 60 seconds |
GET /markets/info | You need one composite market snapshot with config and near-live values. | 1 second |
GET /markets/config | You need slower-changing market configuration without frequently changing value fields. | 30 seconds |
GET /markets/values | You need frequently changing open interest, pool amounts, funding, borrowing, and virtual inventory values. | 1 second |
GET /markets/trading-capacity | You need the current JIT-aware increase capacity for one market symbol and long or short direction. | 1 second |
GET /risk-oracle/markets | You need the active market list expected by the configured risk oracle. | 60 seconds |
Use the split config and values endpoints when your integration can cache static-like market settings separately from fast-changing market state. Use /markets/info when one coherent response is more important than minimizing payload size.
The market responses can include the following configuration and value fields. The eight side-specific *Interest*Using*Token fields are optional and may be absent:
| Response | Fields |
|---|---|
/markets/config and /markets/info | maxCollateralSumLongTokenLong, maxCollateralSumLongTokenShort, maxCollateralSumShortTokenLong, maxCollateralSumShortTokenShort, minFundingIncreaseRatePerSecond, side-specific minimum and maximum funding factors, and virtualIndexTokenId |
/markets/values and /markets/info | virtualInventoryForPositionsInTokens; longInterestUsdUsingLongToken, longInterestUsdUsingShortToken, shortInterestUsdUsingLongToken, shortInterestUsdUsingShortToken; and the corresponding four *InterestInTokensUsing*Token fields |
API responses are extensible, so integrations should ignore unknown fields and define local types around the fields they consume. SDK v2 exposes the split reads as fetchMarketsConfig() and fetchMarketsValues(), returning RawMarketConfig[] and RawMarketValues[]. Direct HTTP integrations can call the corresponding endpoints and define local types around the fields they use.
The GMX API also exposes GET /risk-oracle/markets for the active market list expected by the configured risk oracle. Direct HTTP integrations can call it on the same https://{chain}.gmxapi.io/v1 or https://{chain}.gmxapi.ai/v1 base URLs.
Each GET /markets/values row includes updatedAt, expressed as Unix time in milliseconds. This value is the older of the main market-values refresh and the virtualInventoryForPositionsInTokens refresh, so it represents the least-recent component in that row. It is null when either component has no successful refresh timestamp.
The backend retains the last successful values through a total pull failure instead of replacing the snapshot with empty data. The retained timestamp continues to age, so compare updatedAt with your own freshness limit. With the default 5 second pull interval, the backend marks values older than 15 seconds as stale for monitoring but can still serve them. A market-specific failed refresh can leave the prior values in place with updatedAt: null. Disabled markets are excluded from backend staleness accounting.
JIT liquidity history responses can return longLiquidityUsd: null or shortLiquidityUsd: null; integrations should treat those as missing side-specific liquidity values rather than parsing errors.
Use GET /markets/trading-capacity?symbol={symbol}&direction=long|short when sizing an increase for one market side. The response separates:
baseAvailableLiquidity: capacity available from the pool without JIT.jitAvailableLiquidity: additional capacity contributed by JIT.availableLiquidity: total current global capacity after JIT, still capped by max open interest.jitDataStatusandmarketDataStatus: whether the inputs are usable or stale.
GET /markets/tickers exposes the same snapshot as capacityLong and capacityShort. Treat JIT-aware capacity as indicative: account eligibility, collateral swaps, and intervening market state can reduce what one order can use. Order preparation is the final request-specific check. When the capacity inputs are authoritative, a Market Increase above availableLiquidity fails with INSUFFICIENT_LIQUIDITY; resting increases can instead return an INSUFFICIENT_LIQUIDITY validation warning because capacity will be checked again when they trigger. If the API cannot validate capacity authoritatively because market or JIT data is unavailable, account eligibility is unknown, or collateral requires a swap, prepare returns a TRADING_CAPACITY_UNAVAILABLE warning instead. The warning's details.reason is STALE_MARKET_DATA, JIT_DATA_UNAVAILABLE, JIT_ACCOUNT_ELIGIBILITY_UNKNOWN, or COLLATERAL_SWAP. Prepare waits at most 500 ms for an in-flight JIT data refresh. If JIT data still isn't fresh, the API validates the increase against capacity without JIT and returns the JIT_DATA_UNAVAILABLE warning for a size above that capacity but within max open interest.
availableLiquidityLong and availableLiquidityShort on GET /markets/tickers are legacy fields. They report the GM pool value not needed to back current reserves, exclude JIT, and ignore max open interest. Do not size increases from them: use capacityLong / capacityShort or GET /markets/trading-capacity.
Compare GM pool fee APY and trader PnL
Use GMX API GET /yield/gm-pools when one view needs fee-only APY and trader PnL for the same GM pools and time window. This is distinct from the Oracle API /apy snapshot. SDK v2 exposes the route through fetchGmPoolYieldPnl() in @gmx-io/sdk 1.8.0.
The route accepts period, an optional pools address filter, and includeComponents. feeApy matches the fee-only baseApy calculation from /apy: it includes trading, swap, liquidation, and borrowing fees, but excludes incentives, trader PnL, and backing-token price changes. Positive tradersPnlUsd and tradersPnlApr mean traders gained against the pool; negate the value when estimating the pool-side yield effect.
Responses are cached for 1800 seconds. Inspect each row's hour-aligned window.endTimestamp for freshness. Young pools use their shorter listed window, missing indexed metrics are null, unknown but valid pool addresses are ignored, and malformed addresses return 400.
Read GM LP fee earnings for one account
Use GMX API GET /yield/gm-user-earnings when you need the fees one wallet has earned as a GM liquidity provider on one chain. The response has one row per GM market token the wallet has ever held, including pools that were delisted since. The route is available on the Arbitrum, Avalanche, and MegaETH hosts.
curl "https://arbitrum.gmxapi.io/v1/yield/gm-user-earnings?account=0x9f7198eb1b9Ccc0Eb7A07eD228d8FbC12963ea33"
{
"account": "0x9f7198eb1b9Ccc0Eb7A07eD228d8FbC12963ea33",
"window": { "days": 7, "startTimestamp": 1790305005, "endTimestamp": 1790909805 },
"pools": [
{
"marketToken": "0x728Ff0679c89267434D6EF1824c8C8eED4aC3DBC",
"lifetimeFeeUsd": "119151143989498278743449433765",
"recent7dFeeUsd": "5876284392758426880699403476"
}
]
}
lifetimeFeeUsdandrecent7dFeeUsdare USD amounts encoded as 30-decimal fixed-point integer strings. Divide by10^30to get dollars.windowis the trailing 7-day window used forrecent7dFeeUsd, in Unix seconds.endTimestampis when the API calculated the response.- Only GM tokens held in the wallet on that chain count. GM tokens in a GMX Account or bridged to another chain aren't attributed to the wallet.
- A missing or malformed
accountreturns400. A503means earnings data isn't ready on that deployment yet, for example while an instance warms up; retry with backoff.
In TypeScript, SDK v2 exposes the route as apiSdk.fetchGmUserEarnings({ account }) and returns the USD amounts as strings. For GLV vault earnings, use the GraphQL glvUserEarnings resolver described in GraphQL.
Read protocol-wide stats
Use the GMX API /stats routes when you need protocol-wide volume, fees, revenue, TVL, open interest, users, and trade counts. The stats are chain-agnostic: one response covers the arbitrum, avalanche, megaeth, and solana networks and GMX v1 and v2, whichever chain host you call.
| Route | Use it for | Parameters |
|---|---|---|
GET /stats/summary | Cumulative volume, fees, revenue, users, and trades, plus 24-hour volume and fees, open interest, and TVL, split by network and by version | Optional networks and versions filters |
GET /stats/timeseries | One daily metric over time | Required metric; optional groupBy (network by default, version, or none), networks, versions, from, and to |
GET /stats/sources | Freshness and health of each data source | None |
# Summary for GMX V2 on Arbitrum and Avalanche. Repeat a list parameter for each value.
curl "https://arbitrum.gmxapi.io/v1/stats/summary?networks=arbitrum&networks=avalanche&versions=v2"
# Daily total volume per GMX version
curl "https://arbitrum.gmxapi.io/v1/stats/timeseries?metric=volume.total&groupBy=version&from=1790208000&to=1790899200"
Only the Arbitrum deployment computes the stats. The Arbitrum hosts serve them directly, the other gmxapi.io hosts forward /v1/stats to the Arbitrum deployment, and the other gmxapi.ai hosts answer with a 308 redirect to https://arbitrum.gmxapi.ai. The redirect doesn't carry CORS headers, so browser clients must call an Arbitrum host directly, and server clients that use another .ai host must follow redirects (for example, curl -L). In TypeScript, getStatsApiUrl() from @gmx-io/sdk/configs/api returns https://arbitrum.gmxapi.io, and the standalone fetchApiProtocolStatsSummary(), fetchApiProtocolStatsTimeseries(), and fetchApiProtocolStatsSources() functions from @gmx-io/sdk/v2 take an HTTP client context:
import { GmxApiSdk, fetchApiProtocolStatsSummary } from "@gmx-io/sdk/v2";
const apiSdk = new GmxApiSdk({ chainId: 42161 });
const summary = await fetchApiProtocolStatsSummary(apiSdk.ctx, {
networks: ["arbitrum", "avalanche"],
versions: ["v2"],
});
console.log(summary.meta.completeness, summary.totals.volume.total);
Read the responses with these rules:
- USD amounts are 30-decimal fixed-point integer strings; user and trade counts are numbers. A
nullfield means the source can't provide that value; it never stands in for zero. timeseriesacceptsmetricvaluesvolume.perps,volume.swaps,volume.total,fees.trading,fees.swap,fees.total,revenue.protocol,revenue.lp,trades.perps,trades.swaps, andusers.active.fromandtoare whole Unix seconds and are floored to the UTC day. Each point is{ day, value, provisional };provisional: truemarks a day that can still change.meta.completenessiscompleteonly when every source in scope isfresh. A stale source still counts toward the sums, so checkmeta.sources[](health,lagSeconds, andlastError) before you treat totals as current.- User counts carry
distinctness: "source": a wallet counts once per network and version it's active on, so totals across sources can count the same wallet more than once. openInterestvalues open position size in index tokens at the current oracle mid price, so it moves with prices, the same methodGET /pairsuses.- A filter that matches no configured source, such as
networks=megaeth&versions=v1, returns400.
Read positions and related orders for one account
Use SDK v2 if you are already in TypeScript and want bigint-aware responses. Use the generated GMX API reference if you need raw HTTP schemas.
Install @gmx-io/sdk, then import GmxApiSdk from @gmx-io/sdk/v2. The v2 path is a subpath export, not a separate package.
import { GmxApiSdk } from "@gmx-io/sdk/v2";
const apiSdk = new GmxApiSdk({ chainId: 42161 });
const positions = await apiSdk.fetchPositionsInfo({
address: "0x9f7198eb1b9Ccc0Eb7A07eD228d8FbC12963ea33",
includeRelatedOrders: true,
});
const orders = await apiSdk.fetchOrders({
address: "0x9f7198eb1b9Ccc0Eb7A07eD228d8FbC12963ea33",
});
console.log({
positions,
orders,
});
Both GET /positions and GET /positions/{key} return positionValueInUsd. The API derives it from PositionReader.getPositionInfo, including collateral, claimable funding, base PnL, total price impact, and execution costs. For an account list, the Reader calls for all returned positions use one block number, so the position values share a common on-chain snapshot.
If the Reader's full-close simulation reverts with PriceImpactLargerThanOrderSize because closing the position would cost more price impact than its size, the API reads that position again at the same block without the close simulation. It then rebuilds positionValueInUsd off-chain from the full-size PnL plus the capped negative price impact, -maxPositionImpactFactorNegative * sizeInUsd. This fallback doesn't cap PnL by maxPnlFactorForTraders, so a large positive PnL can be slightly overstated for that position. Other Reader reverts still fail the request.
The list and detail routes have a 1 second response cache. A position that closes before the Reader snapshot is omitted from the list or returns 404 from the detail route. Related orders come from the API's order store and are not part of the common-block Reader call.
Direct HTTP returns positionValueInUsd as a decimal string. SDK v2 deserializes it to bigint and exposes it on ApiPositionInfo.
Use this flow when you render account state:
- Fetch positions with
includeRelatedOrders: trueif your page shows open positions and their linked orders together. - Fetch standalone orders only if you also need an account-wide orders view.
- After submitting a write through SDK v1 or direct contracts, poll these read endpoints until the expected state appears instead of assuming immediate consistency.
Read historical trade activity
Use SDK v2 or the GMX API for API-backed trade-history reads, and use GraphQL when you need full indexed history or custom analytics. Do not try to reconstruct history from live market snapshots.
import { GmxApiSdk } from "@gmx-io/sdk/v2";
const apiSdk = new GmxApiSdk({ chainId: 42161 });
const trades = await apiSdk.fetchTrades({
address: "0x9f7198eb1b9Ccc0Eb7A07eD228d8FbC12963ea33",
limit: 50,
});
const filteredTrades = await apiSdk.searchTrades({
address: "0x9f7198eb1b9Ccc0Eb7A07eD228d8FbC12963ea33",
fromTimestamp: 1767225600,
limit: 50,
});
For lower-level integrations, the generated GMX API reference documents the raw /trades and /trades/search schemas.
GraphQL remains useful for indexed analytics:
query RecentTrades($account: String!) {
tradeActions(where: { account_eq: $account }, limit: 50, orderBy: timestamp_DESC) {
eventName
account
timestamp
transactionHash
sizeDeltaUsd
collateralDeltaAmount
}
}
The current GraphQL schema exposes transactionHash and top-level timestamp. See GraphQL for schema usage notes and migration context.
For referral analytics, the GraphQL schema also exposes the affiliateStats and traderReferralStats resolvers, plus per-hour stats entities (AffiliateReferralTradeStatsByHour, TraderReferralTradeStatsByHour, AffiliateTraderStatsByHour). Use these instead of stitching tradeActions for affiliate dashboards or trader rebate views — both resolvers accept from/to time windows and return pre-aggregated volume, rebate, discount, and trader-flow figures. TraderReferralTradeStatsByHour.affiliateRewardsUsd, TraderFirstReferral, ReferralTier, and ReferrerTier support referral-code update accounting, while the private referralCodeUpdates resolver is not intended for public integrations. See GraphQL — Referral analytics for the full schema and example queries.
Operational notes
Freshness and caching
- Oracle API
GET /marketsuses a10second HTTP cache in the current implementation. - Oracle API
GET /markets/infouses a10second HTTP cache in the current implementation. - Oracle API
GET /markets/stateuses a5second HTTP cache in the current implementation. - GMX API
GET /yield/gm-poolsuses a1800second cached snapshot; usewindow.endTimestamprather than response arrival time to measure freshness. - GMX API
GET /yield/gm-user-earningscaches each account's response for2seconds. The backend refreshes the fee accumulators it uses from the synthetics-stats subgraph every5seconds by default. - GMX API
/stats/*responses are cached for30seconds. By default, the backend pulls source snapshots every60seconds, syncs daily rows every10minutes, and marks a sourcestalewhen its data lags by more than900seconds. Usemeta.sources[].lagSecondsrather than response arrival time to measure freshness. - GMX API
GET /pairs/solana, which aggregators read athttps://solana.gmxapi.io/v1/pairs, serves a snapshot rebuilt every60seconds and caches the response for60seconds. It returns503instead of an empty list or a snapshot older than15minutes. - GMX API
GET /incentives/usdg/boost-aprresponses are cached for1800seconds, andGET /whitelistsresponses for60seconds per address. - The backend currently caches
prices,tokensData, andmarketsInfofor1second,userReferralInfofor5seconds, andonchainSettingsfor60seconds. - Avoid joining data from unrelated polls when you need one coherent snapshot. Prefer composite endpoints such as
/markets/infoorfetchPositionsInfo({ includeRelatedOrders: true }).
Retries, timeouts, and fallback URLs
- The current API server timeout is
60000ms. - SDK v2 uses
HttpClientWithFallbackwith the hosts in its configuration and any additional hosts supplied by your application. In the current publishedlatest,2.2.1, the packaged fallback list is empty for every chain, so an SDK integration has no peer to fail over to until your application supplies the second host. You still own request retry timing, backoff, and user-facing recovery behavior. - Use the Fallback URLs page for Oracle API market and oracle reads.
- If you receive a timeout, network error,
429, or5xx, retry with backoff and fail over where you have fallback endpoints. Don't fail over in the middle of an express order chain; see Idempotency and race conditions. /v1/statson a non-Arbitrumgmxapi.aihost answers with a308redirect tohttps://arbitrum.gmxapi.ai. Follow redirects, or call an Arbitrum host directly.
Surface-specific operational model
- The Oracle API is deployed per chain on
https://{chain}-api.gmxinfra.ioprimary hosts, uses endpoint-specific cache windows, and documents fallback URLs for some public reads. - The GMX API is deployed per chain across two independent peer base URLs (
https://{chain}.gmxapi.io/v1andhttps://{chain}.gmxapi.ai/v1). Both are equal; there is no primary/secondary. Clients that hit the API directly can use either base URL or rotate across both for reads. The two peers are independent deployments that don't share order-transaction records, so an express order chain must stay on one host. The generated reference does not define your retry policy. - GraphQL is indexed data. Expect lag relative to live chain state.
- SDK v1 mixes live RPC, oracle, and indexed reads. Default SDK-created HTTP transports disable retries.
- SDK v2 is an HTTP client for reads and API-relayed order workflows. Its transport supports peer failover across configured hosts, but the packaged host list is empty in the current published
latest,2.2.1, so your integration must supply the peer hosts and define its own application-level retry policy. With fallback hosts configured, SDK v22.1.1and later send an express order's submit and status calls to the host that served its prepare, without cross-host fallback. - Direct contracts give you the most control, but your app owns retry, nonce, gas, and receipt strategy.
- Delegated trading flows run through
SubaccountGelatoRelayRouterorMultichainSubaccountRouterand have their own session lifecycle — your integration owns subaccount authorization, expiry, action-count tracking, and relay-nonce handling. See Delegated trading integration.
Idempotency and race conditions
- For SDK v2 and API-relayed order workflows, persist the
requestIdreturned by prepare or submit calls and poll order status instead of resubmitting blindly. - Keep an express order's prepare, submit, and status calls on the GMX API host that served prepare. The
requestIdrecord exists only in that host's deployment, so a status call on the peer host returns404. If the host that served prepare returns a5xx, or404for status, don't send the samerequestIdto the peer host: prepare the order again. Before you prepare again after a submit attempt, check the account's orders so you don't place the same order twice. The same rule applies to GMX Account cross-chain withdrawal submit and status calls. - For direct generic-relay flows, persist the
taskIdreturned byPOST /relay/submitand pollPOST /relay/status. Treatunknownas inconclusive rather than failed, and don't submit the same signed operation again merely because status is temporarily unavailable. The/relay/*routes are a stateless proxy that keeps no per-host record, so the host pinning above doesn't apply to them. - After a write, do not assume your first follow-up read will reflect final state. Submission, relay processing, keeper execution, and indexing can land at different times.
- If you need "position plus linked orders" on one screen, prefer a single positions call with
includeRelatedOrders: trueover stitching data from independent polls.
Next steps
- Use API Overview to decide between the GMX API, Oracle API, GraphQL, contracts, and the SDK.
- Use Getting GM and GLV token prices when you need to choose between Chainlink Data Feeds, direct Reader calls, and API or SDK data for GM/GLV valuation.
- Use the Oracle API for public market, price, and liquidity endpoints.
- Use the generated GMX API OpenAPI Reference for endpoint-level request and response schemas.
- Use Troubleshooting if your reads look stale, a query fails validation, or a write does not show up yet.
- Use SDK v2 when your application needs API-relayed order flows.
- Use SDK v1 when your application needs direct RPC-backed write flows such as creating or canceling orders.
- Use Delegated trading integration when you need subaccount-based, gasless, or one-click order flows on behalf of a user.