Skip to main content
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 below) — migrate before it’s retired.
x-api-key is now required. Every v3 request authenticates against an active API key. See 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.

Response shape

The same request shown in full for v2 and v3, plus a focused diff of what moved.
The full OpenAPI schema lives at 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

The x-api-key request header is now required. Every request authenticates against an active API key. See API Keys for details.
v3 exposes a broad filter surface. All parameters are optional and combine with AND semantics unless noted.
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.
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.
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.
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.
The parallel appFees (quoted) and paidAppFees (actual) arrays are consolidated into one object with explicit quoted / actual keys and a hoisted currency.
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.
Inside inTxs[] and outTxs[], the hash field is renamed to txHash. The array names themselves are unchanged.
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.
  • 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).
  • supersededByRequestId is promoted to the root; it previously lived at data.supersededByRequestId in v2. When a deposit-address request is regenerated (currently Bitcoin/BVM only), the original request’s supersededByRequestId points to the regenerated requestId that owns the sweep and fill. null otherwise.
  • 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

Migration checklist

1

Switch the endpoint and headers

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).
2

Update fee reads

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.
3

Repoint currency & route reads

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.
4

Consolidate app fees & sponsorship

Read data.appFees.quoted / data.appFees.actual. Replace subsidizedRequest/subsidizedFee with data.feeSponsorship, and rename its relay bucket to platform.
5

Fix tx hashes, statuses & nulls

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".
6

Adopt the new querying surface

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.