diff --git a/docs.json b/docs.json index fa2962d..d91fa81 100644 --- a/docs.json +++ b/docs.json @@ -119,6 +119,12 @@ "references/api/api_guides/webhooks" ] }, + { + "group": "Migration Guides", + "pages": [ + "references/api/api_guides/migrating-to-requests-v3" + ] + }, { "group": "Chains, Tokens, Contracts", "pages": [ @@ -155,6 +161,7 @@ { "group": "Deprecated", "pages": [ + "references/api/get-requests-v2", "references/api/get-price", "references/api/get-config", "references/api/get-intents-status", diff --git a/references/api/api_core_concepts/fees.mdx b/references/api/api_core_concepts/fees.mdx index bb14095..f238963 100644 --- a/references/api/api_core_concepts/fees.mdx +++ b/references/api/api_core_concepts/fees.mdx @@ -115,25 +115,29 @@ _Please note that the above fee structure applies to standard cases. In certain ## Fees in the API -Both the quote API and the requests API return a request's fees in the `expandedPriceImpact` object, which breaks them down into the following components: +[`GET /requests/v3`](/references/api/get-requests) returns a request's fees in the `data.fees` object, with `quoted` (estimated at quote time) and `actual` (computed at fill time) values. It breaks fees down into the following components: **execution** - Execution fees covering network gas on the origin and/or destination chain plus the flat fee. **swap** - Swap costs from cross-currency and cross-chain exchange, including DEX fees, swap slippage, and solver rebalancing. -**relay** - The Relay fee, the flat basis-point fee charged by Relay for routing and meta-aggregation services. +**platform** - The platform fee, the flat basis-point fee charged by Relay for routing and meta-aggregation services. **app** - App fees added on top by the integrator, when present. **sponsored** - The portion of fees the integrator subsidizes on behalf of the user via [Fee Sponsorship](/features/fee-sponsorship). -When displaying fees to users, we recommend mapping the `expandedPriceImpact` fields as follows: -- **relay** → Provider Fee +When displaying fees to users, we recommend mapping the `data.fees` fields as follows: +- **platform** → Provider Fee - **app** → Your App's Fee - **swap** + **execution** → Swap Impact + +In the quote API and [`GET /requests/v2`](/references/api/get-requests-v2), this same breakdown is returned as the `expandedPriceImpact` object, and the **platform** component is named **relay**. + + ## Fee Sponsorship Integrators with [Fee Sponsorship](/features/fee-sponsorship) enabled can subsidize fees for their users. By default, setting **`subsidizeFees`** to `true` sponsors all fee components. @@ -147,9 +151,9 @@ See the [Fee Sponsorship Doc](/features/fee-sponsorship) for setup details. ## Deprecated: Fees Object -The `fees` object is deprecated. It is still returned from the quote API and the [`GET /requests/v2`](/references/api/get-requests) API for backwards compatibility, but it only reports Relay-related fees and does not reflect the full cost of a request. Do not rely on it for new integrations. +The `fees` object is deprecated. It is still returned from the quote API and the [`GET /requests/v2`](/references/api/get-requests-v2) API for backwards compatibility, but it only reports Relay-related fees and does not reflect the full cost of a request. Do not rely on it for new integrations. -To understand or display the complete fee breakdown of a request, use the [`expandedPriceImpact`](#fees-in-the-api) object instead, which covers execution, swap, relay, app, and sponsored fees. +To understand or display the complete fee breakdown of a request, use the [`data.fees`](#fees-in-the-api) object in `GET /requests/v3` (or `expandedPriceImpact` in the quote API and `GET /requests/v2`) instead, which covers execution, swap, platform, app, and sponsored fees. The deprecated `fees` object is segmented into the following fields: diff --git a/references/api/api_guides/migrating-to-requests-v3.mdx b/references/api/api_guides/migrating-to-requests-v3.mdx new file mode 100644 index 0000000..58f0058 --- /dev/null +++ b/references/api/api_guides/migrating-to-requests-v3.mdx @@ -0,0 +1,505 @@ +--- +title: "Migrating to Requests v3" +description: "What changed in GET /requests/v3 and how to upgrade from v2." +--- + +`GET /requests/v3` is the latest version of the Requests API. It gives you a richer query surface with advanced filtering across status, chains, amounts, addresses, time, and more, plus a cleaner and more consistent response. This guide covers every change and how to upgrade. `GET /requests/v2` remains available during a deprecation window (see the [sunset timeline](#sunset-timeline) below) — migrate before it's retired. + + + `x-api-key` is now required. Every v3 request authenticates against an active API key. See [API Keys](/references/api/api-keys) for details. + + +## Sunset timeline + +`GET /requests/v2` is **deprecated as of July 22, 2026**. It keeps working, but migrate to `GET /requests/v3` before it's fully retired on **November 24, 2026**. + +| Date | What changes | +| --- | --- | +| **Jul 22, 2026** | v2 is deprecated; v3 is the recommended version. v2 keeps working. | +| **Sep 1, 2026 onward** | v2's rate limit is progressively reduced each month; requests over the limit receive `429`. | +| **Nov 24, 2026** | v2 is fully retired — all traffic must be on v3. | + +## Response shape + +The same request shown in full for v2 and v3, plus a focused diff of what moved. + + + + ```json expandable + { + "id": "0x0000348634...", + "status": "success", + "user": "0xe7a2052a...", + "recipient": "0x07082933...", + "depositAddress": null, + "moonpayId": null, + "referrer": "my-app|user-123", + "data": { + "slippageTolerance": "0", + "failReason": "N/A", + "refundFailReason": "N/A", + "subsidizedRequest": true, + "price": "10000000000", + "currency": "usdc", + "currencyObject": { "chainId": 8453, "address": "0x833589...", "symbol": "USDC", "name": "USD Coin", "decimals": 6, "metadata": { "logoURI": "https://...", "verified": true } }, + "feeCurrency": "usdc.e", + "feeCurrencyObject": { "chainId": 137, "address": "0x2791bc...", "symbol": "USDC.e", "name": "USDCoin (bridged)", "decimals": 6, "metadata": { "logoURI": "https://...", "verified": true } }, + "appFeeCurrencyObject": { "chainId": 137, "address": "0x2791bc...", "symbol": "USDC.e", "name": "USDCoin (bridged)", "decimals": 6 }, + "fees": { "gas": "1160", "fixed": "0", "price": "1999930" }, + "feesUsd": { "gas": "0.001159", "fixed": "0.000000", "price": "1.999162" }, + "appFees": [ { "recipient": "0xdfd877...", "bps": "5", "amount": "5000000", "amountUsd": "4.997980", "amountUsdCurrent": "4.998080" } ], + "paidAppFees": [ { "recipient": "0xdfd877...", "bps": "5", "amount": "5000000", "amountUsd": "4.997980", "amountUsdCurrent": "4.998080" } ], + "subsidizedFee": { + "origin": { "amount": "7001090", "address": "0x2791bc...", "chainId": 137 }, + "sponsor": { "amount": "7000949", "address": "0x833589...", "chainId": 8453 }, + "amountUsd": "6.998261", + "amountUsdCurrent": "6.998401" + }, + "expandedPriceImpact": { + "quoted": { "swap": { "usd": "-1.999380" }, "execution": { "usd": "-0.001160" }, "relay": { "usd": "0.000000" }, "app": { "usd": "-4.998625" }, "sponsored": { "usd": "6.999165" } }, + "actual": { "swap": { "usd": "-1.999380" }, "execution": { "usd": "-0.001160" }, "relay": { "usd": "0.000000" }, "app": { "usd": "-4.998625" }, "sponsored": { "usd": "6.999165" } } + }, + "feeSponsorship": { + "quoted": { + "selectedComponents": ["execution", "swap", "relay", "app"], + "capHit": false, + "components": { + "execution": { "selected": true, "total": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "1160", "amountFormatted": "0.00116", "amountUsd": "0.001160", "minimumAmount": "1160" }, "sponsored": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "1160", "amountUsd": "0.001160" }, "userPays": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "0", "amountUsd": "0" } }, + "swap": { "selected": true, "total": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "1999380", "amountUsd": "1.999380" }, "sponsored": { "amount": "1999380", "amountUsd": "1.999380" }, "userPays": { "amount": "0", "amountUsd": "0" } }, + "relay": { "selected": true, "total": { "amount": "0", "amountUsd": "0.000000" }, "sponsored": { "amount": "0", "amountUsd": "0" }, "userPays": { "amount": "0", "amountUsd": "0" } }, + "app": { "selected": true, "total": { "amount": "5000000", "amountUsd": "4.998625" }, "sponsored": { "amount": "5000000", "amountUsd": "4.998625" }, "userPays": { "amount": "0", "amountUsd": "0" } } + }, + "sponsoredTotal": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "7001090", "amountFormatted": "7.00109", "amountUsd": "6.999165" }, + "userPaysTotal": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "0", "amountUsd": "0" } + }, + "actual": { "selectedComponents": ["execution", "swap", "relay", "app"], "capHit": false, "components": { "execution": "…", "swap": "…", "relay": "…", "app": "…" }, "sponsoredTotal": { "amount": "7001090", "amountUsd": "6.999165" }, "userPaysTotal": { "amount": "0", "amountUsd": "0" } } + }, + "inTxs": [ { "hash": "0xcd4d70...", "fee": "139725000000000", "block": 87433122, "type": "onchain", "chainId": 137, "timestamp": 1779747672, "status": "success", "data": {}, "stateChanges": [] } ], + "outTxs": [ { "hash": "0x1c0089...", "fee": "433800000000", "block": 46479163, "type": "onchain", "chainId": 8453, "timestamp": 1779747673, "status": "success", "data": {}, "stateChanges": [] } ], + "usesExternalLiquidity": false, + "timeEstimate": 4, + "metadata": { + "sender": "0xE7a205...", + "recipient": "0x070829...", + "currencyIn": { "currency": { "chainId": 137, "address": "0x2791bc...", "symbol": "USDC.e", "name": "USDCoin (bridged)", "decimals": 6, "metadata": { "logoURI": "https://...", "verified": true } }, "amount": "10000000000", "amountFormatted": "10000.0", "amountUsd": "9997.600000", "amountUsdCurrent": "9996.000000", "minimumAmount": "10000000000" }, + "currencyOut": { "currency": { "chainId": 8453, "address": "0x833589...", "symbol": "USDC", "name": "USD Coin", "decimals": 6, "metadata": { "logoURI": "https://...", "verified": true } }, "amount": "10000000000", "amountFormatted": "10000.0", "amountUsd": "9997.600000", "amountUsdCurrent": "9996.000000", "minimumAmount": "10000000000" }, + "rate": "1", + "route": { + "origin": { "inputCurrency": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "10000000000" }, "outputCurrency": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "10000000000" }, "router": "relay" }, + "destination": { "inputCurrency": { "currency": { "chainId": 8453, "symbol": "USDC", "decimals": 6 }, "amount": "10000000000" }, "outputCurrency": { "currency": { "chainId": 8453, "symbol": "USDC", "decimals": 6 }, "amount": "10000000000" }, "router": "relay" } + } + } + }, + "protocol": { + "orderId": "0x...", + "hubType": "onchain", + "isWithdrawable": false, + "solver": { "address": "0x...", "protocolChainId": "8453", "chainId": 8453 }, + "deposit": { "origin": { "amount": "10000000000", "chainId": 137, "currency": "0x2791bc...", "depositor": "0xe7a205...", "depository": "0x...", "onchainId": "0x...", "transactionId": "0xcd4d70..." } }, + "settlement": { "destination": { "fills": [ { "chainId": 8453, "transactionId": "0x1c0089..." } ], "refunds": [] } } + }, + "createdAt": "2026-05-25T22:21:11.161Z", + "updatedAt": "2026-05-25T22:21:51.291Z" + } + ``` + + + ```json expandable + { + "id": "0x0000348634...", + "status": "success", + "user": "0xe7a2052a...", + "sender": "0xE7a205...", + "recipient": "0x07082933...", + "refundTo": null, + "depositAddress": null, + "requestType": "Bridge", + "data": { + "slippageTolerance": "0", + "failReason": null, + "refundFailReason": null, + "failedTxHash": null, + "failedTxBlockNumber": null, + "failedCallData": null, + "usesExternalLiquidity": false, + "timeEstimate": 4, + "triggeredByFastFill": null, + "inTxs": [ { "txHash": "0xcd4d70...", "fee": "139725000000000", "block": 87433122, "type": "onchain", "chainId": 137, "timestamp": 1779747672, "status": "success", "data": {}, "stateChanges": [] } ], + "outTxs": [ { "txHash": "0x1c0089...", "fee": "433800000000", "block": 46479163, "type": "onchain", "chainId": 8453, "timestamp": 1779747673, "status": "success", "data": {}, "stateChanges": [] } ], + "appFees": { + "quoted": [ { "recipient": "0xdfd877...", "bps": "5", "amount": "5000000", "amountFormatted": "5.0" } ], + "actual": [ { "recipient": "0xdfd877...", "bps": "5", "amount": "5000000", "amountFormatted": "5.0", "amountUsd": "4.997980" } ], + "currency": { "chainId": 137, "address": "0x2791bc...", "symbol": "USDC.e", "name": "USDCoin (bridged)", "decimals": 6, "metadata": { "logoURI": "https://...", "verified": true } } + }, + "fees": { + "quoted": { "swap": { "usd": "-1.999380", "amount": "1999380", "amountFormatted": "1.99938" }, "execution": { "usd": "-0.001160", "amount": "1160", "amountFormatted": "0.00116" }, "platform": { "usd": "0.000000", "amount": "0", "amountFormatted": "0" }, "app": { "usd": "-4.998625", "amount": "5000000", "amountFormatted": "5.0" }, "sponsored": { "usd": "6.999165", "amount": "7001090", "amountFormatted": "7.00109" } }, + "actual": { "swap": { "usd": "-1.999380" }, "execution": { "usd": "-0.001160" }, "platform": { "usd": "0.000000" }, "app": { "usd": "-4.998625" }, "sponsored": { "usd": "6.999165" } }, + "currency": { "chainId": 137, "address": "0x2791bc...", "symbol": "USDC.e", "name": "USDCoin (bridged)", "decimals": 6, "metadata": { "logoURI": "https://...", "verified": true } } + }, + "feeSponsorship": { + "quoted": { + "selectedComponents": ["execution", "swap", "platform", "app"], + "maxSubsidizationAmount": null, + "capHit": false, + "components": { + "execution": { "selected": true, "total": { "amount": "1160", "amountFormatted": "0.00116", "amountUsd": "0.001160", "minimumAmount": "1160" }, "sponsored": { "amount": "1160", "amountUsd": "0.001160" }, "userPays": { "amount": "0", "amountUsd": "0" } }, + "swap": { "selected": true, "total": { "amount": "1999380", "amountUsd": "1.999380" }, "sponsored": { "amount": "1999380", "amountUsd": "1.999380" }, "userPays": { "amount": "0", "amountUsd": "0" } }, + "platform": { "selected": true, "total": { "amount": "0", "amountUsd": "0" }, "sponsored": { "amount": "0", "amountUsd": "0" }, "userPays": { "amount": "0", "amountUsd": "0" } }, + "app": { "selected": true, "total": { "amount": "5000000", "amountUsd": "4.998625" }, "sponsored": { "amount": "5000000", "amountUsd": "4.998625" }, "userPays": { "amount": "0", "amountUsd": "0" } } + }, + "sponsoredTotal": { "amount": "7001090", "amountFormatted": "7.00109", "amountUsd": "6.999165" }, + "userPaysTotal": { "amount": "0", "amountFormatted": "0", "amountUsd": "0" } + }, + "actual": { "selectedComponents": ["execution", "swap", "platform", "app"], "capHit": false, "components": { "execution": "…", "swap": "…", "platform": "…", "app": "…" }, "sponsoredTotal": { "amount": "7001090", "amountUsd": "6.999165" }, "userPaysTotal": { "amount": "0", "amountUsd": "0" }, "sponsorPayment": { "amount": "7000949", "address": "0x833589...", "chainId": 8453 } }, + "currency": { "chainId": 137, "address": "0x2791bc...", "symbol": "USDC.e", "decimals": 6 } + }, + "route": { + "includedSwapSources": [], + "includedOriginSwapSources": [], + "includedDestinationSwapSources": [], + "quoted": { + "origin": { "inputCurrency": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "10000000000" }, "outputCurrency": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "10000000000" }, "router": "relay" }, + "destination": { "inputCurrency": { "currency": { "chainId": 8453, "symbol": "USDC", "decimals": 6 }, "amount": "10000000000" }, "outputCurrency": { "currency": { "chainId": 8453, "symbol": "USDC", "decimals": 6 }, "amount": "10000000000" }, "router": "relay" } + }, + "actual": { + "rate": "1", + "origin": { "inputCurrency": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "10000000000" }, "outputCurrency": { "currency": { "chainId": 137, "symbol": "USDC.e", "decimals": 6 }, "amount": "10000000000" }, "router": "relay" }, + "destination": { "inputCurrency": { "currency": { "chainId": 8453, "symbol": "USDC", "decimals": 6 }, "amount": "10000000000" }, "outputCurrency": { "currency": { "chainId": 8453, "address": "0x833589...", "symbol": "USDC", "name": "USD Coin", "decimals": 6, "metadata": { "logoURI": "https://...", "verified": true } }, "amount": "10000000000", "amountFormatted": "10000.0", "amountUsd": "9997.600000" }, "router": "relay" } + } + }, + "platformFee": null, + "quoteOraclePrice": null, + "referrer": "my-app|user-123", + "refundCurrencyData": null, + "externalMetadata": { "moonpayId": null } + }, + "protocol": { + "orderId": "0x...", + "hubType": "onchain", + "isWithdrawable": false, + "solver": { "address": "0x...", "protocolChainId": "8453", "chainId": 8453 }, + "deposit": { "origin": { "amount": "10000000000", "chainId": 137, "currency": "0x2791bc...", "depositor": "0xe7a205...", "depository": "0x...", "onchainId": "0x...", "transactionId": "0xcd4d70..." } }, + "settlement": { "destination": { "fills": [ { "chainId": 8453, "transactionId": "0x1c0089..." } ], "refunds": [] } } + }, + "features": ["app_fees"], + "createdAt": "2026-05-25T22:21:11.161Z", + "updatedAt": "2026-05-25T22:21:51.291Z" + } + ``` + + + ```jsonc expandable + { + "id": "0x0000348634...", + "status": "success", + "moonpayId": null, // [!code --] + "sender": "0xE7a205...", // [!code ++] promoted from data.metadata.sender + "refundTo": null, // [!code ++] + "requestType": "Bridge", // [!code ++] + "depositAddress": null, // now an object: { address, type, depositor, depositTxHash, recoveryAddress } + "referrer": "my-app|user-123", // [!code --] moved to data.referrer (authenticated) + "features": ["app_fees"], // [!code ++] + "data": { + "failReason": "N/A", // [!code --] + "refundFailReason": "N/A", // [!code --] + "failReason": null, // [!code ++] + "refundFailReason": null, // [!code ++] + "subsidizedRequest": true, // [!code --] + "price": "10000000000", // [!code --] removed; read data.route.actual.destination.inputCurrency + "fees": { "gas": "1160", "fixed": "0", "price": "1999930" }, // [!code --] + "feesUsd": { "gas": "0.001159" }, // [!code --] + "currency": "usdc", // [!code --] + "currencyObject": { }, // [!code --] + "feeCurrency": "usdc.e", // [!code --] + "feeCurrencyObject": { }, // [!code --] + "appFees": [ { "bps": "5", "amount": "5000000", "amountUsd": "4.99" } ], // [!code --] + "paidAppFees": [ { "bps": "5", "amount": "5000000", "amountUsd": "4.99" } ], // [!code --] + "appFees": { // [!code ++] + "quoted": [ { "bps": "5", "amount": "5000000" } ], // [!code ++] + "actual": [ { "bps": "5", "amount": "5000000", "amountUsd": "4.99" } ], // [!code ++] + "currency": { "symbol": "USDC.e", "decimals": 6 } // [!code ++] + }, // [!code ++] + "subsidizedFee": { "amountUsd": "6.99" }, // [!code --] + "expandedPriceImpact": { "quoted": { "relay": { "usd": "0" } } }, // [!code --] + "fees": { // [!code ++] + "quoted": { "swap": {}, "execution": {}, "platform": {}, "app": {}, "sponsored": {} }, // [!code ++] + "actual": { }, // [!code ++] + "currency": { "symbol": "USDC.e", "decimals": 6 } // [!code ++] + }, // [!code ++] + "feeSponsorship": { + "quoted": { "selectedComponents": ["execution","swap","relay","app"], "components": { "relay": {} } } // [!code --] + "quoted": { "selectedComponents": ["execution","swap","platform","app"], "components": { "platform": {} } }, // [!code ++] + "actual": { "sponsorPayment": { "amount": "...", "chainId": 8453 } }, // [!code ++] + "currency": { "symbol": "USDC.e", "decimals": 6 } // [!code ++] + }, + "inTxs": [ { "hash": "0xcd4d70..." } ], // [!code --] + "outTxs": [ { "hash": "0x1c0089..." } ], // [!code --] + "inTxs": [ { "txHash": "0xcd4d70..." } ], // [!code ++] + "outTxs": [ { "txHash": "0x1c0089..." } ], // [!code ++] + "metadata": { "sender": "…", "currencyIn": {}, "currencyOut": {}, "rate": "1", "route": {} }, // [!code --] + "route": { // [!code ++] + "includedSwapSources": [], // [!code ++] + "quoted": { "origin": {}, "destination": {} }, // [!code ++] + "actual": { "rate": "1", "origin": {}, "destination": {} } // [!code ++] + }, // [!code ++] + "referrer": "my-app|user-123", // [!code ++] authenticated; moved from root + "externalMetadata": { "moonpayId": null } // [!code ++] + } + } + ``` + + + + + The full OpenAPI schema lives at [api.relay.link/documentation/json](https://api.relay.link/documentation/json). + + + + **`data.fees` has changed meaning.** The key `fees` is reused for a different shape. In v2, `data.fees` was raw wei (`gas`/`fixed`/`price`/`gateway`). In v3 that object is removed, and `data.fees` now holds the per-component USD breakdown that v2 called `expandedPriceImpact`. Code reading `data.fees.gas` will break — read `data.fees.quoted` / `data.fees.actual` instead. + + +## What changed + +Every individual change, grouped by request side and response side. + +### Request & querying + + + + ```bash + GET /requests/v3 + Headers: + x-api-key: # now required [!code ++] + ``` + + The `x-api-key` request header is now required. Every request authenticates against an active API key. See [API Keys](/references/api/api-keys) for details. + + + + v3 exposes a broad filter surface. All parameters are optional and combine with AND semantics unless noted. + + | Category | Parameters | + | --- | --- | + | **Search** | `term` (request id, wallet, deposit address, every tx hash), `id`, `orderId`, `depositTxHash`, `fillTxHash`, `refundTxHash` | + | **Chain** | `originChainId`, `destinationChainId`, `chainId` (either direction), `privateChainsToInclude` | + | **Address** | `user`, `depositAddress`, `recipient` | + | **Status / routing** | `status`, `failReason`, `refundFailReason`, `apiKey`, `requestType` | + | **Currency** | `currencyInChainId`, `currencyOutChainId`, `currencyInAddress`, `currencyOutAddress`, `currencyInSymbol`, `currencyOutSymbol` | + | **Ranges** | `startTimestamp`, `endTimestamp`, `startBlock`, `endBlock`, `amountUsdMin`/`Max`, `appFeesAmountUsdMin`/`Max`, `fillTimeMin`/`Max` | + | **Other** | `features`, `includeChildRequests`, `filters` (AND/OR), `sortBy`, `sortDirection`, `includeAuthenticatedData` | + + + `term` is a single unified search across request id, wallet, deposit address, and every transaction hash (deposit, fill, refund, failed, chain-entry). It replaces the v2 pattern of running separate `user` / `hash` / `id` lookups and merging the results. + + + **Sorting.** `sortBy` accepts `createdAt` (default), `updatedAt`, or `amountUsd`. `sortDirection` is `asc` or `desc` (defaults to `desc` for time fields, `asc` for `amountUsd`). + + **Advanced filtering (AND / OR / negation).** The `filters` parameter takes a JSON-encoded array of groups. Fields **within** a group are AND'd; the groups themselves are OR'd. Any key can be negated with a `not:` prefix, and a field's value may be an array (OR within that field). Top-level parameters still apply. + + ```bash + # "(depositAddress=0xabc AND originChainId=8453) OR (depositAddress=0x123 AND originChainId=1)" + GET /requests/v3?filters=[{"depositAddress":"0xabc","originChainId":8453},{"depositAddress":"0x123","originChainId":1}] + + # negation + array value: everything except failures and refunds + GET /requests/v3?filters=[{"not:status":["failure","refund"]}] + ``` + + OR groups support identity, address, chain, currency, and status-style fields. Range filters and `features` are top-level only. + + **Removed & changed parameters.** + - `hash` is removed; use `term`, or the targeted `depositTxHash` / `fillTxHash` / `refundTxHash`. + - `referrer` is no longer a query parameter; it's still returned in the response, but only when `includeAuthenticatedData=true`. + + + + +### Response fields + + + + The `currency` (string) + `currencyObject` (object) duality is removed everywhere, along with `feeCurrency`/`feeCurrencyObject` and `appFeeCurrencyObject`. Every currency is a single object: `{ chainId, address, symbol, name, decimals, metadata }`. Amount objects carry that currency plus `amount`, `amountFormatted`, `amountUsd`, and where relevant `amountUsdCurrent`, `minimumAmount`. + + ```jsonc + "currency": "usdc", // [!code --] + "currencyObject": { "chainId": 137, "symbol": "USDC", "decimals": 6 } // [!code --] + // read the currency object directly off the amount, [!code ++] + // e.g. data.route.actual.origin.inputCurrency.currency [!code ++] + ``` + + + + `data.expandedPriceImpact` is renamed to **`data.fees`** (and the old wei `data.fees` / `data.feesUsd` are removed). Each phase (`quoted`, `actual`) breaks fees into `swap`, `execution`, `platform`, `app`, and `sponsored`, with the shared currency hoisted to `data.fees.currency`. The `relay` component is renamed to **`platform`**, and per-component values now include `amount` and `amountFormatted` in addition to `usd`. + + ```jsonc + "expandedPriceImpact": { "quoted": { "swap": { "usd": "-1.99" }, "relay": { "usd": "0" } } } // [!code --] + "fees": { // [!code ++] + "quoted": { "swap": { "usd": "-1.99", "amount": "...", "amountFormatted": "..." }, "platform": { "usd": "0" } }, // [!code ++] + "actual": { "...": "..." }, // [!code ++] + "currency": { "symbol": "USDC.e" } // [!code ++] + } // [!code ++] + ``` + + + + `data.subsidizedRequest` and `data.subsidizedFee` are removed. `data.feeSponsorship` is now the only sponsorship source — determine whether a request was sponsored from `feeSponsorship.{quoted,actual}.sponsoredTotal.amountUsd`. The `relay` bucket is renamed to **`platform`**, the shared `currency` is hoisted to `feeSponsorship.currency`, and the `actual` phase gains a `sponsorPayment` object. + + ```jsonc + "subsidizedRequest": true, // [!code --] + "subsidizedFee": { "amountUsd": "6.99" }, // [!code --] + "feeSponsorship": { + "quoted": { "selectedComponents": ["execution","swap","relay","app"], "components": { "relay": {} } } // [!code --] + "quoted": { "selectedComponents": ["execution","swap","platform","app"], "components": { "platform": {} } }, // [!code ++] + "actual": { "sponsorPayment": { "amount": "...", "chainId": 8453 } }, // [!code ++] + "currency": { "symbol": "USDC.e" } // [!code ++] + } + ``` + + + + The parallel `appFees` (quoted) and `paidAppFees` (actual) arrays are consolidated into one object with explicit `quoted` / `actual` keys and a hoisted `currency`. + + ```jsonc + "appFees": [ { "bps": "5", "amount": "5000000" } ], // [!code --] + "paidAppFees": [ { "bps": "5", "amount": "5000000", "amountUsd": "4.99" } ], // [!code --] + "appFees": { // [!code ++] + "quoted": [ { "bps": "5", "amount": "5000000" } ], // [!code ++] + "actual": [ { "bps": "5", "amount": "5000000", "amountUsd": "4.99" } ], // [!code ++] + "currency": { "symbol": "USDC.e" } // [!code ++] + } // [!code ++] + ``` + + + + The `data.metadata` catch-all is removed. `sender` is promoted to the **root** (next to `recipient`), and everything else moves into **`data.route`**, which now has two phases: + + - `data.route.quoted` — the route as quoted at request time. + - `data.route.actual` — what actually executed. Carries `rate`, and `actual` falls back to `quoted` when there's no execution data yet (e.g. same-chain swaps). + + Each phase has `origin` and `destination` sides, and each side has `inputCurrency` / `outputCurrency` (each a full amount object) plus `router` (on the `actual` route, `router` reflects the provider that actually filled the leg, not always `"relay"`). `includedSwapSources` / `includedOriginSwapSources` / `includedDestinationSwapSources` are hoisted to the top of `data.route`. + + There is **no `data.swap`** and **no `data.quotedOutputAmount`** — read amounts from the route instead: + + - Amount deposited: `data.route.actual.origin.inputCurrency` (→ `quoted`). + - Amount received: `data.route.actual.destination.outputCurrency` (→ `quoted`). For same-chain swaps there is no destination side, so fall back to `origin.outputCurrency`. + + ```jsonc + "metadata": { "sender": "…", "currencyIn": {}, "currencyOut": {}, "rate": "1", "route": {} } // [!code --] + // sender → promoted to the root [!code ++] + "route": { // [!code ++] + "includedSwapSources": [], // [!code ++] + "quoted": { "origin": {}, "destination": {} }, // [!code ++] + "actual": { "rate": "1", "origin": {}, "destination": {} } // [!code ++] + } // [!code ++] + ``` + + + + Inside `inTxs[]` and `outTxs[]`, the `hash` field is renamed to `txHash`. The array names themselves are unchanged. + + ```jsonc + "inTxs": [ { "hash": "0xcd4d70..." } ], // [!code --] + "outTxs": [ { "hash": "0x1c0089..." } ] // [!code --] + "inTxs": [ { "txHash": "0xcd4d70..." } ], // [!code ++] + "outTxs": [ { "txHash": "0x1c0089..." } ] // [!code ++] + ``` + + + + The response `status` enum is now `pending`, `waiting`, `depositing`, `submitted`, `success`, `failure`, `refund`. `depositing` and `submitted` are new; the v2 `delayed` value is gone. The `status` **filter** accepts `success`, `failure`, `refund`, `pending`, `depositing`. + + ```jsonc + status ∈ { pending, waiting, delayed, success, failure, refund } // [!code --] + status ∈ { pending, waiting, depositing, submitted, success, failure, refund } // [!code ++] + ``` + + + + - `moonpayId` moves from the root to **`data.externalMetadata.moonpayId`**. + - `sender` is **promoted to the root** (next to `recipient`); it previously lived in `data.metadata.sender`. + - `referrer` moves into **`data.referrer`** and is returned **only when `includeAuthenticatedData=true`**. It's also no longer a query parameter. + - **`refundTo`** (refund target for deposit-address transactions) is **added** at the root. + - **`requestType`** (`Bridge`, `Crosschain Swap`, `Same-chain Swap`, `Send`, `Wrap`, `Unwrap`, `Call`) is **added** at the root. + - **`features`** (e.g. `gasless_execution`, `fast_fill`, `gas_top_up`, `app_fees`, `deposit_address`) is **added** at the root. + - **`depositAddress`** is now a structured object: `{ address, type: "strict" | "open", depositor, depositTxHash, recoveryAddress }`. `recoveryAddress` is the origin-chain address that can recover deposit-address funds if the recipient wallet is later blocked (`null` when not set). + - **`data.quoteOraclePrice`** is **added** — the oracle price snapshot at quote time (`{ rate, observedAt, inputCurrency, outputCurrency }`), returned only for fixed-BPS oracle integrators; `null` otherwise. + - `data.price` is **removed** — read the quoted output amount from `data.route.actual.destination.inputCurrency` (distinct from the actual received amount in `data.route.actual.destination.outputCurrency`). + - `failReason` / `refundFailReason` use **`null`** instead of the string `"N/A"`. + + + +## Field migration reference + + + + | v2 | v3 | + | --- | --- | + | `data.expandedPriceImpact` | `data.fees` (component `relay` → `platform`) | + | `data.metadata.sender` | `sender` (root) | + | `data.metadata.recipient` | `recipient` (root) | + | `data.metadata.{currencyIn,currencyOut,rate,currencyGasTopup}` | `data.route.{quoted,actual}.*` | + | `data.metadata.route` | `data.route.{quoted,actual}` | + | `data.appFees` (quoted) + `data.paidAppFees` (actual) | `data.appFees.{quoted,actual,currency}` | + | `inTxs[].hash` / `outTxs[].hash` | `inTxs[].txHash` / `outTxs[].txHash` | + | `feeSponsorship…components.relay` | `feeSponsorship…components.platform` | + | `moonpayId` (root) | `data.externalMetadata.moonpayId` | + | `depositAddress` (nullable) | `depositAddress` object `{address,type,depositor,depositTxHash}` | + + + | Removed in v3 | Replacement | + | --- | --- | + | `data.fees` (wei `gas`/`fixed`/`price`/`gateway`) | `data.fees` (now USD price-impact) | + | `data.feesUsd` | `data.fees` | + | `data.currency` / `data.currencyObject` | currency object on each amount | + | `data.feeCurrency` / `data.feeCurrencyObject` | currency hoisted into fee objects | + | `data.appFeeCurrencyObject` | `data.appFees.currency` | + | `data.subsidizedRequest` / `data.subsidizedFee` | `data.feeSponsorship` | + | `data.metadata` (catch-all) | `data.route.{quoted,actual}` (`sender` promoted to root) | + | `data.price` | read `data.route.actual.destination.inputCurrency` | + | `referrer` (query parameter) | removed as a filter; still returned in the response when `includeAuthenticatedData=true` | + | `?hash` | `term` / `depositTxHash` / `fillTxHash` / `refundTxHash` | + | status `delayed` | `depositing` / `submitted` | + + + | Added in v3 | Notes | + | --- | --- | + | `requestType` | request type (`Bridge`, `Crosschain Swap`, `Same-chain Swap`, `Send`, `Wrap`, `Unwrap`, `Call`) | + | `sender` (root) | promoted from `data.metadata.sender` | + | `features` (root) | request feature flags (`gasless_execution`, `fast_fill`, `app_fees`, …) | + | `refundTo` | refund target for deposit-address flows | + | `depositAddress.recoveryAddress` | origin-chain address that can recover deposit-address funds if the recipient is later blocked | + | `data.quoteOraclePrice` | oracle price snapshot at quote time (`rate`, `observedAt`, `inputCurrency`, `outputCurrency`); fixed-BPS oracle integrators only | + | `data.route.actual` | executed route (with `rate`); falls back to `quoted` | + | `data.externalMetadata` | partner correlation IDs (e.g. `moonpayId`) | + | `feeSponsorship.actual.sponsorPayment` | what the sponsor actually paid | + | broad filter/sort surface | see [Filtering, search & sorting](#what-changed) | + + + +## Migration checklist + + + + Point requests at `GET /requests/v3` and send `x-api-key` (now required). Drop the `referrer` query parameter. Set `includeAuthenticatedData=true` only from a trusted server context to receive authenticated fields (see the note at the end). + + + Stop reading `data.fees.gas` / `feesUsd`. Read the per-component USD breakdown from `data.fees.quoted` / `data.fees.actual`, and rename the `relay` component to `platform`. + + + Replace `data.metadata.*` reads: `sender` is now at the root, and currencies/rate come from `data.route.{quoted,actual}` (prefer `actual`, fall back to `quoted`). Read the deposited amount from `route.actual.origin.inputCurrency` and the received amount from `route.actual.destination.outputCurrency` (fall back to `origin.outputCurrency` for same-chain swaps). Drop `currency`/`currencyObject` string handling — read the single currency object. + + + Read `data.appFees.quoted` / `data.appFees.actual`. Replace `subsidizedRequest`/`subsidizedFee` with `data.feeSponsorship`, and rename its `relay` bucket to `platform`. + + + Rename `inTxs[].hash` / `outTxs[].hash` to `txHash`. Handle the new `depositing` / `submitted` statuses (and remove `delayed`). Treat `failReason` / `refundFailReason` as `null` rather than `"N/A"`. + + + Replace separate `user`/`hash`/`id` lookups with a single `term` search where it fits, and take advantage of the new filter/sort parameters. Pagination is unchanged — keep passing `continuation` back for the next page (`limit` max 50). + + + + + Authenticated data is only returned when you pass `includeAuthenticatedData=true` and authenticate with an API key tied to those requests. + + + diff --git a/references/api/changelog.mdx b/references/api/changelog.mdx index e2193d3..fe501e4 100644 --- a/references/api/changelog.mdx +++ b/references/api/changelog.mdx @@ -3,6 +3,11 @@ title: "API Changelog" description: "Record of breaking changes, deprecations, and notable additions to the Relay API" --- +## 2026-07-22 — `GET /requests/v3` is live; `GET /requests/v2` deprecated & scheduled for sunset + +**Added** — `GET /requests/v3`: the recommended Requests API. It requires `x-api-key`, adds a broad filter/search/sort surface, and returns a cleaner, consolidated response. See the [migration guide](/references/api/api_guides/migrating-to-requests-v3). + +**Deprecated** — `GET /requests/v2` is deprecated as of today. It keeps working for now, but its rate limit will be progressively reduced each month until it is **fully retired on November 24, 2026**. Migrate to v3 before then — see the [sunset timeline](/references/api/api_guides/migrating-to-requests-v3#sunset-timeline). ## 2026-07-09 — Solana quote size check reserves compute-budget headroom **Behavior change** — `POST /quote/v2`: the Solana deposit-transaction size check on cross-chain Solana-origin quotes now reserves 60 bytes of headroom for the compute-budget instructions wallets and SDKs prepend at send time, so quotes are rejected when the compiled deposit transaction would exceed **1172 bytes** (1232 minus 60). Previously the check ran at the raw 1232-byte limit and could return `200` with calldata that no longer fit once the client added its compute-budget instructions. The `400` response body now names the effective limit and the reserved-bytes reason. Continue to use **`maxRouteLength`** or **`includedOriginSwapSources`** to keep transactions under the limit — see [Solana Support](/references/api/api_guides/solana#transaction-size-optimization). diff --git a/references/api/get-requests-v2.mdx b/references/api/get-requests-v2.mdx new file mode 100644 index 0000000..f8ea6c0 --- /dev/null +++ b/references/api/get-requests-v2.mdx @@ -0,0 +1,9 @@ +--- +title: "Get Requests (v2)" +description: "Deprecated. Returns cross-chain transactions. Use GET /requests/v3 for new integrations." +openapi: get /requests/v2 +--- + + + `GET /requests/v2` is **deprecated as of July 22, 2026** and is being sunset: its rate limit is reduced each month until it is **fully retired on November 24, 2026**. New integrations should use [`GET /requests/v3`](/references/api/get-requests), which requires authentication and offers a richer filter surface and a cleaner response. See the [migration guide](/references/api/api_guides/migrating-to-requests-v3#sunset-timeline) for the full timeline and how to upgrade. + diff --git a/references/api/get-requests.mdx b/references/api/get-requests.mdx index f634021..6a4a98f 100644 --- a/references/api/get-requests.mdx +++ b/references/api/get-requests.mdx @@ -1,5 +1,5 @@ --- title: "Get Requests" description: "This API returns all the cross-chain transactions." -openapi: get /requests/v2 +openapi: get /requests/v3 --- diff --git a/style.css b/style.css index 04f321a..5f24e53 100644 --- a/style.css +++ b/style.css @@ -387,4 +387,4 @@ callout), adding an unwanted gap. Zero it out. */ .callout .prose > :first-child { margin-top: 0; - } \ No newline at end of file + }