From 63ac4c52e9ce567e88aa5f9ef0131c7a7c796742 Mon Sep 17 00:00:00 2001 From: Nick Koutrelakos Date: Sun, 2 Aug 2026 18:58:36 -0600 Subject: [PATCH 1/7] docs(trading): document the X-Agent-Info attribution header Adds a dedicated page covering the optional X-Agent-Info request header (decision_origin, integration_name, version), the rules that mark it malformed, and the x-agent-info-status response contract used to confirm it parsed. Cross-linked from the swapping API integration guide, troubleshooting page, and the Uniswap AI overview. ECO-639 --- .../swapping-api/agent-attribution.mdx | 82 +++++++++++++++++++ .../trading/swapping-api/common-errors.mdx | 2 + .../swapping-api/integration-guide.mdx | 2 + content/trading/swapping-api/meta.json | 1 + content/uniswap-ai/overview.mdx | 2 + 5 files changed, 89 insertions(+) create mode 100644 content/trading/swapping-api/agent-attribution.mdx diff --git a/content/trading/swapping-api/agent-attribution.mdx b/content/trading/swapping-api/agent-attribution.mdx new file mode 100644 index 000000000..3e74dd735 --- /dev/null +++ b/content/trading/swapping-api/agent-attribution.mdx @@ -0,0 +1,82 @@ +--- +title: Agent Attribution (X-Agent-Info) +description: Send the optional X-Agent-Info header to attribute agent-driven Trading API traffic, and check x-agent-info-status to confirm it was recognized. +--- + +If your integration is built or operated by an AI agent, the Uniswap API accepts an optional `X-Agent-Info` request header so that agent-driven traffic can be measured separately from human-driven traffic. + + + +`X-Agent-Info` is purely for analytics. Humans and human-facing clients can ignore it entirely. Omitting it, sending it, or sending it incorrectly has no effect on your request — it never changes the response status, body, or any swap behavior. + + + +## Sending the header + +Send `X-Agent-Info` alongside your usual [authentication](/docs/trading/swapping-api/integration-guide#authentication) headers, with a JSON object value containing up to three fields: + +| Field | Type | Required | Notes | +| --- | --- | --- | --- | +| `decision_origin` | string | Yes | Must be exactly `autonomous` or `human_mediated` (case-sensitive). Any other value marks the header malformed. | +| `integration_name` | string | No | Name of your integration or agent, e.g. `my-trading-bot`. Up to 256 characters. | +| `version` | string | No | Version identifier for your integration. Up to 256 characters. | + +Any other keys in the object are silently dropped rather than rejected, so it's safe to reuse an object that carries additional fields for your own purposes — only the three fields above are ever attributed. + +```bash +curl -X POST https://trade-api.gateway.uniswap.org/v1/quote \ + -H "x-api-key: YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + -H 'X-Agent-Info: {"decision_origin":"autonomous","integration_name":"my-trading-bot","version":"1.4.0"}' \ + -d '{"tokenIn":"0x...","tokenOut":"0x...","amount":"1000000",...}' +``` + +## What makes a header malformed + +A header is dropped (marked malformed) rather than rejected outright if any of the following hold. The request still succeeds either way — see [Confirming it was received](#confirming-it-was-received) below for how to tell the difference. + +- The raw header value is larger than **1024 bytes** (UTF-8), measured before parsing. +- The value isn't valid JSON, or is valid JSON that isn't a plain object (an array, string, number, boolean, or `null`). +- `decision_origin` is missing, or is anything other than exactly `autonomous` or `human_mediated`. +- `integration_name` or `version` is present but isn't a string, or exceeds 256 characters. +- `integration_name` or `version` contains control characters or unpaired surrogate code points. + +Not sending the header at all, or sending it with an empty value, isn't an error condition — both are simply "no attribution," the same outcome as a header that's out of scope for your client. + +## Confirming it was received + +Because the request succeeds regardless of whether `X-Agent-Info` parsed, check the `x-agent-info-status` response header to confirm your header was actually recognized: + +- **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. This value is a fixed string; it never echoes anything from your request. +- **No `x-agent-info-status` header at all** — this happens when your `X-Agent-Info` header parsed successfully, when you didn't send one, or when the request's response wasn't itself successful (the diagnostic header is only stamped on successful responses). If you're debugging a request that also failed for an unrelated reason (rate limiting, request validation, no route found), the absence of this header doesn't confirm your `X-Agent-Info` header was fine — retry against a request that otherwise succeeds. Attribution is a side channel: on a successful response, a working integration looks identical, from the response alone, to one that sent nothing. + +```typescript +const response = await fetch('https://trade-api.gateway.uniswap.org/v1/quote', { + method: 'POST', + headers: { + 'x-api-key': 'YOUR_API_KEY', + 'Content-Type': 'application/json', + 'X-Agent-Info': JSON.stringify({ + decision_origin: 'autonomous', + integration_name: 'my-trading-bot', + version: '1.4.0', + }), + }, + body: JSON.stringify({ + /* ...quote request... */ + }), +}); + +if (response.headers.get('x-agent-info-status') === 'malformed') { + // Received but dropped — check field names, decision_origin value, and length limits above. + console.warn('X-Agent-Info was sent but not recognized.'); +} + +const quote = await response.json(); +``` + + + +A malformed or missing `X-Agent-Info` header never changes the response status, body, or swap behavior. The worst case is that your traffic isn't attributed to your integration. + + diff --git a/content/trading/swapping-api/common-errors.mdx b/content/trading/swapping-api/common-errors.mdx index 0aef420b6..bb30c1044 100644 --- a/content/trading/swapping-api/common-errors.mdx +++ b/content/trading/swapping-api/common-errors.mdx @@ -9,6 +9,8 @@ description: Troubleshoot common Uniswap API request, quoting, authentication, a The API is specific about request header validation. In particular, ensure that your `accept` and `content-type` headers only include the value `application/json`. For a complete example of properly formatted request headers, see the authentication section of the [Developer Dashboard](https://developers.uniswap.org/dashboard). +If you're sending the optional `X-Agent-Info` attribution header and it isn't being picked up, check the response for an `x-agent-info-status: malformed` header — see [Agent Attribution](/docs/trading/swapping-api/agent-attribution#confirming-it-was-received) for the full set of rules that make the header malformed. + ### Rate limits Most API keys have a default rate limit of 6 requests per second (RPS). If you exceed the rate limit supported by an API key you can expect to receive an HTTP 429 error. If you receive a 429 error, we recommend pausing all requests from your API key and then retrying your requests. If you require a higher rate limit than what your API key is currently provisioned for, please reach out to [Uniswap Developer Support](https://support.uniswap.org/hc/en-us/requests/new). For more information on rate limits, see the [Developer Dashboard](https://developers.uniswap.org/dashboard). diff --git a/content/trading/swapping-api/integration-guide.mdx b/content/trading/swapping-api/integration-guide.mdx index b8ff37079..3c4ff7673 100644 --- a/content/trading/swapping-api/integration-guide.mdx +++ b/content/trading/swapping-api/integration-guide.mdx @@ -48,6 +48,8 @@ const quote = await response.json(); AI builders can consume the full Open API Specification (OAS) at [https://trade-api.gateway.uniswap.org/v1/api.json](https://trade-api.gateway.uniswap.org/v1/api.json). +If your integration is built or operated by an AI agent, also consider sending the optional [`X-Agent-Info` attribution header](/docs/trading/swapping-api/agent-attribution) alongside your request. + Full code examples for completing a basic swap workflow are available in [Swapping Code Examples](/docs/trading/swapping-api/swapping-code-examples). ## Architecture diff --git a/content/trading/swapping-api/meta.json b/content/trading/swapping-api/meta.json index df804dcbe..1ef124c66 100644 --- a/content/trading/swapping-api/meta.json +++ b/content/trading/swapping-api/meta.json @@ -5,6 +5,7 @@ "concepts", "supported-chains", "integration-guide", + "agent-attribution", "chained-actions", "chained-actions-integration", "amm-vs-uniswapx-routing", diff --git a/content/uniswap-ai/overview.mdx b/content/uniswap-ai/overview.mdx index 2a2061062..eb0bf8fb5 100644 --- a/content/uniswap-ai/overview.mdx +++ b/content/uniswap-ai/overview.mdx @@ -5,6 +5,8 @@ description: Get started with Uniswap AI plugins, skills, and LLM context. Use Uniswap AI to speed up swap integration, hook development, and EVM workflows with tools designed for builders on Uniswap. +If your agent talks to the Trading API directly, send the optional [`X-Agent-Info` attribution header](/docs/trading/swapping-api/agent-attribution) so agent-driven traffic is measured separately from human-driven traffic. + ## Uniswap AI The [Uniswap AI repository](https://github.com/Uniswap/uniswap-ai) is an open-source collection of plugins and skills for coding agents. It provides protocol-specific guidance for Uniswap APIs and smart contracts. From f2404202a144e5f161c5500529740ca550070f27 Mon Sep 17 00:00:00 2001 From: Nick Koutrelakos Date: Tue, 1 Sep 2026 11:44:11 -0700 Subject: [PATCH 2/7] docs(trading): correct X-Agent-Info parse rules and status-header behavior Adds the printable-ASCII, duplicate-header, and full disallowed-character rules to the malformed list. Corrects the field cap to UTF-16 code units and the size cap to raw bytes. Replaces the extra-keys guidance with an explicit rule against identifying values. Fixes the claim that x-agent-info-status only appears on successful responses; it also rides the gateway's own error responses. Makes the curl example's request body valid JSON. --- .../swapping-api/agent-attribution.mdx | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/content/trading/swapping-api/agent-attribution.mdx b/content/trading/swapping-api/agent-attribution.mdx index 3e74dd735..db3b7b04b 100644 --- a/content/trading/swapping-api/agent-attribution.mdx +++ b/content/trading/swapping-api/agent-attribution.mdx @@ -18,28 +18,33 @@ Send `X-Agent-Info` alongside your usual [authentication](/docs/trading/swapping | Field | Type | Required | Notes | | --- | --- | --- | --- | | `decision_origin` | string | Yes | Must be exactly `autonomous` or `human_mediated` (case-sensitive). Any other value marks the header malformed. | -| `integration_name` | string | No | Name of your integration or agent, e.g. `my-trading-bot`. Up to 256 characters. | -| `version` | string | No | Version identifier for your integration. Up to 256 characters. | +| `integration_name` | string | No | Name of your integration or agent, e.g. `my-trading-bot`. Up to 256 UTF-16 code units — JavaScript's `String#length`. | +| `version` | string | No | Version identifier for your integration. Up to 256 UTF-16 code units. | -Any other keys in the object are silently dropped rather than rejected, so it's safe to reuse an object that carries additional fields for your own purposes — only the three fields above are ever attributed. +Send only these three fields. Any other key is dropped rather than rejected, so an extra key never makes the header malformed. + +`integration_name` and `version` are stored per request and queried later. Both must be stable strings that describe your software. Never send a user ID, wallet address, email address, session token, API key, or any value derived from an end user. On our side, a malformed header is never echoed back or logged, and only the three fields above ever reach our analytics. ```bash +# Fill in your own token addresses and amount. The header is evaluated either way. curl -X POST https://trade-api.gateway.uniswap.org/v1/quote \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H 'X-Agent-Info: {"decision_origin":"autonomous","integration_name":"my-trading-bot","version":"1.4.0"}' \ - -d '{"tokenIn":"0x...","tokenOut":"0x...","amount":"1000000",...}' + -d '{"tokenIn":"0x...","tokenOut":"0x...","amount":"1000000"}' ``` ## What makes a header malformed A header is dropped (marked malformed) rather than rejected outright if any of the following hold. The request still succeeds either way — see [Confirming it was received](#confirming-it-was-received) below for how to tell the difference. -- The raw header value is larger than **1024 bytes** (UTF-8), measured before parsing. +- The raw header value is larger than **1024 bytes**, measured on the raw value before parsing. JSON whitespace and `\u` escapes count toward the cap. +- The raw header value contains any byte outside printable US-ASCII (`0x20`–`0x7E`). This is checked first, before the JSON is parsed, because bytes above `0x7E` decode differently in different HTTP stacks. So a literal `é`, an emoji, or a curly quote in the header marks it malformed no matter how short the value is. Send non-ASCII as a JSON `\u` escape instead. - The value isn't valid JSON, or is valid JSON that isn't a plain object (an array, string, number, boolean, or `null`). +- The request carried two or more `X-Agent-Info` header lines. They are joined with `", "`, which is almost never valid JSON. Set the header once rather than appending to it — some HTTP clients append by default. - `decision_origin` is missing, or is anything other than exactly `autonomous` or `human_mediated`. -- `integration_name` or `version` is present but isn't a string, or exceeds 256 characters. -- `integration_name` or `version` contains control characters or unpaired surrogate code points. +- `integration_name` or `version` is present but isn't a string, or is longer than 256 UTF-16 code units. That count is JavaScript's `String#length`, so an emoji or other astral character costs two units, not one. +- `integration_name` or `version` contains a disallowed character. Those are control characters (C0 `0x00`–`0x1F`, DEL `0x7F`, C1 `0x80`–`0x9F`), the Unicode line separators U+2028 and U+2029, and the replacement character U+FFFD. An escaped unpaired surrogate decodes to U+FFFD, so it is rejected too. Text pasted from a PDF, or left behind by a lossy re-encode, often carries one of these invisibly. Not sending the header at all, or sending it with an empty value, isn't an error condition — both are simply "no attribution," the same outcome as a header that's out of scope for your client. @@ -47,8 +52,12 @@ Not sending the header at all, or sending it with an empty value, isn't an error Because the request succeeds regardless of whether `X-Agent-Info` parsed, check the `x-agent-info-status` response header to confirm your header was actually recognized: -- **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. This value is a fixed string; it never echoes anything from your request. -- **No `x-agent-info-status` header at all** — this happens when your `X-Agent-Info` header parsed successfully, when you didn't send one, or when the request's response wasn't itself successful (the diagnostic header is only stamped on successful responses). If you're debugging a request that also failed for an unrelated reason (rate limiting, request validation, no route found), the absence of this header doesn't confirm your `X-Agent-Info` header was fine — retry against a request that otherwise succeeds. Attribution is a side channel: on a successful response, a working integration looks identical, from the response alone, to one that sent nothing. +- **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. The value is always the fixed string `malformed`; it never echoes anything from your request. +- **No `x-agent-info-status` header at all** — your `X-Agent-Info` header parsed, or you didn't send one. + +The gateway sets this header before it validates or routes your request, so error responses carry it too. A 400 or a 429 still tells you whether your header parsed. You can debug the header without first getting a working quote. + +Browser clients need no extra setup. The gateway lists its own response header names in `Access-Control-Expose-Headers` on each response, so JavaScript can read `x-agent-info-status` cross-origin. ```typescript const response = await fetch('https://trade-api.gateway.uniswap.org/v1/quote', { From 5a5f4ea8c11ec4f384cfb898e7251ad65f10b037 Mon Sep 17 00:00:00 2001 From: Nick Koutrelakos Date: Tue, 1 Sep 2026 11:57:33 -0700 Subject: [PATCH 3/7] docs(trading): correct when the gateway stamps x-agent-info-status The header is set after routing and before any response is written, not before validation. Note that an unrouted 404 does not carry it. --- content/trading/swapping-api/agent-attribution.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/trading/swapping-api/agent-attribution.mdx b/content/trading/swapping-api/agent-attribution.mdx index db3b7b04b..0aae4093a 100644 --- a/content/trading/swapping-api/agent-attribution.mdx +++ b/content/trading/swapping-api/agent-attribution.mdx @@ -55,7 +55,7 @@ Because the request succeeds regardless of whether `X-Agent-Info` parsed, check - **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. The value is always the fixed string `malformed`; it never echoes anything from your request. - **No `x-agent-info-status` header at all** — your `X-Agent-Info` header parsed, or you didn't send one. -The gateway sets this header before it validates or routes your request, so error responses carry it too. A 400 or a 429 still tells you whether your header parsed. You can debug the header without first getting a working quote. +The gateway sets this header after it routes your request and before it writes any response. Its own error responses carry it too — a 400, a 401, a 403, a 429. So you can debug the header without first getting a working quote. One exception: a 404 for a path the gateway does not route carries no status header. Browser clients need no extra setup. The gateway lists its own response header names in `Access-Control-Expose-Headers` on each response, so JavaScript can read `x-agent-info-status` cross-origin. From cba1447ca49bac7802c0013035779cdbd609d844 Mon Sep 17 00:00:00 2001 From: Nick Koutrelakos Date: Tue, 1 Sep 2026 12:09:24 -0700 Subject: [PATCH 4/7] docs(trading): correct CORS scope, 404 wording, and request examples for X-Agent-Info --- .../swapping-api/agent-attribution.mdx | 27 ++++++++++--------- .../trading/swapping-api/common-errors.mdx | 2 +- content/uniswap-ai/overview.mdx | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/content/trading/swapping-api/agent-attribution.mdx b/content/trading/swapping-api/agent-attribution.mdx index 0aae4093a..2b9171c6a 100644 --- a/content/trading/swapping-api/agent-attribution.mdx +++ b/content/trading/swapping-api/agent-attribution.mdx @@ -3,11 +3,11 @@ title: Agent Attribution (X-Agent-Info) description: Send the optional X-Agent-Info header to attribute agent-driven Trading API traffic, and check x-agent-info-status to confirm it was recognized. --- -If your integration is built or operated by an AI agent, the Uniswap API accepts an optional `X-Agent-Info` request header so that agent-driven traffic can be measured separately from human-driven traffic. +The Uniswap API accepts an optional `X-Agent-Info` request header. Send it if an AI agent built or operates your integration. It lets us measure agent-driven traffic separately from human-driven traffic. - + -`X-Agent-Info` is purely for analytics. Humans and human-facing clients can ignore it entirely. Omitting it, sending it, or sending it incorrectly has no effect on your request — it never changes the response status, body, or any swap behavior. +`X-Agent-Info` is purely for analytics. Humans and human-facing clients can ignore it entirely. Omitting it, sending it, or sending it incorrectly has no effect on your request. It never changes the response status, body, or any swap behavior. @@ -31,7 +31,7 @@ curl -X POST https://trade-api.gateway.uniswap.org/v1/quote \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H 'X-Agent-Info: {"decision_origin":"autonomous","integration_name":"my-trading-bot","version":"1.4.0"}' \ - -d '{"tokenIn":"0x...","tokenOut":"0x...","amount":"1000000"}' + -d '{"tokenIn":"0x...","tokenOut":"0x...","tokenInChainId":1,"tokenOutChainId":1,"type":"EXACT_INPUT","amount":"1000000","swapper":"0x...","slippageTolerance":0.5}' ``` ## What makes a header malformed @@ -55,9 +55,9 @@ Because the request succeeds regardless of whether `X-Agent-Info` parsed, check - **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. The value is always the fixed string `malformed`; it never echoes anything from your request. - **No `x-agent-info-status` header at all** — your `X-Agent-Info` header parsed, or you didn't send one. -The gateway sets this header after it routes your request and before it writes any response. Its own error responses carry it too — a 400, a 401, a 403, a 429. So you can debug the header without first getting a working quote. One exception: a 404 for a path the gateway does not route carries no status header. +The gateway sets this header after it routes your request, and before it writes its own response. Its own error responses carry it too — a 400, a 401, a 403, a 429. So you can debug the header without first getting a working quote. Two cases carry no status header: a 404 for a path the API does not serve, and a CORS preflight. -Browser clients need no extra setup. The gateway lists its own response header names in `Access-Control-Expose-Headers` on each response, so JavaScript can read `x-agent-info-status` cross-origin. +Call the Trading API server-to-server. The gateway sends CORS headers only to allow-listed Uniswap origins, so a browser page on your own domain cannot read this header. Check it from a server or with curl. ```typescript const response = await fetch('https://trade-api.gateway.uniswap.org/v1/quote', { @@ -72,7 +72,14 @@ const response = await fetch('https://trade-api.gateway.uniswap.org/v1/quote', { }), }, body: JSON.stringify({ - /* ...quote request... */ + tokenIn: '0x...', + tokenOut: '0x...', + tokenInChainId: 1, + tokenOutChainId: 1, + type: 'EXACT_INPUT', + amount: '1000000', + swapper: '0x...', + slippageTolerance: 0.5, }), }); @@ -84,8 +91,4 @@ if (response.headers.get('x-agent-info-status') === 'malformed') { const quote = await response.json(); ``` - - -A malformed or missing `X-Agent-Info` header never changes the response status, body, or swap behavior. The worst case is that your traffic isn't attributed to your integration. - - +The only consequence of a malformed header is that your traffic isn't attributed to your integration. diff --git a/content/trading/swapping-api/common-errors.mdx b/content/trading/swapping-api/common-errors.mdx index bb30c1044..95af4cd50 100644 --- a/content/trading/swapping-api/common-errors.mdx +++ b/content/trading/swapping-api/common-errors.mdx @@ -9,7 +9,7 @@ description: Troubleshoot common Uniswap API request, quoting, authentication, a The API is specific about request header validation. In particular, ensure that your `accept` and `content-type` headers only include the value `application/json`. For a complete example of properly formatted request headers, see the authentication section of the [Developer Dashboard](https://developers.uniswap.org/dashboard). -If you're sending the optional `X-Agent-Info` attribution header and it isn't being picked up, check the response for an `x-agent-info-status: malformed` header — see [Agent Attribution](/docs/trading/swapping-api/agent-attribution#confirming-it-was-received) for the full set of rules that make the header malformed. +If you're sending the optional `X-Agent-Info` attribution header and it isn't being picked up, check the response for an `x-agent-info-status: malformed` header — see [Agent Attribution](/docs/trading/swapping-api/agent-attribution#confirming-it-was-received) for the full set of rules that make the header malformed. A malformed `X-Agent-Info` never causes an error response; the request proceeds without attribution. ### Rate limits diff --git a/content/uniswap-ai/overview.mdx b/content/uniswap-ai/overview.mdx index eb0bf8fb5..1bb646c00 100644 --- a/content/uniswap-ai/overview.mdx +++ b/content/uniswap-ai/overview.mdx @@ -97,7 +97,7 @@ https://developers.uniswap.org/llms-full.txt ### Claude Code -Install the Uniswap AI plugins (see [above](#install-as-a-claude-code-plugin)) for the richest integration. The plugins provide structured skills, expert agents, and protocol-specific tools that go beyond static documentation context. +Install the Uniswap AI plugins (see [above](#claude-code-marketplace)) for the richest integration. The plugins provide structured skills, expert agents, and protocol-specific tools that go beyond static documentation context. ## Where to Go Next From 77230483393169353ddf5a299e301e8e3e86dd5d Mon Sep 17 00:00:00 2001 From: Nick Koutrelakos Date: Tue, 1 Sep 2026 12:19:26 -0700 Subject: [PATCH 5/7] docs(trading): list the seven required /quote fields instead of autoSlippage autoSlippage is optional in the published OpenAPI spec. The required set is type, amount, tokenInChainId, tokenOutChainId, tokenIn, tokenOut, swapper. --- content/trading/swapping-api/common-errors.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/trading/swapping-api/common-errors.mdx b/content/trading/swapping-api/common-errors.mdx index 95af4cd50..5eea937cd 100644 --- a/content/trading/swapping-api/common-errors.mdx +++ b/content/trading/swapping-api/common-errors.mdx @@ -27,7 +27,7 @@ The most commonly encountered HTTP error is an HTTP 404 with a message "No quote ### 400 Request validation error -Request validation errors are returned when a request does not contain the minimum required set of fields or has other syntactical errors. Some examples are a required field (ex. `autoSlippage` in the [`/quote`](/docs/trading/swapping-api/getting-started) endpoint) is not populated, or an address is missing a character (eg. is 39 characters long instead of 40). These errors typically include a specific error message which describes the field which could not be interpreted. +Request validation errors are returned when a request does not contain the minimum required set of fields or has other syntactical errors. Some examples are a required field is not populated ([`/quote`](/docs/trading/swapping-api/getting-started) requires `type`, `amount`, `tokenInChainId`, `tokenOutChainId`, `tokenIn`, `tokenOut`, and `swapper`), or an address is missing a character (eg. is 39 characters long instead of 40). These errors typically include a specific error message which describes the field which could not be interpreted. ### 401 Unauthorized error From 8ff8ffa922f96ba637b6b8b3c67e8722fc3e792b Mon Sep 17 00:00:00 2001 From: Nick Koutrelakos Date: Tue, 1 Sep 2026 17:23:08 -0700 Subject: [PATCH 6/7] docs(trading): a 404 carries x-agent-info-status, and the CORS allow-list is not Uniswap-only The gateway writes no 404 of its own. Unknown paths fall through to the default upstream, which answers after the status header is stamped, so a 404 carries it. Verified against production: GET /nope returns 404 with x-agent-info-status: malformed. Only a CORS preflight skips it. The CORS allow-list also holds a few partner domains, so "Uniswap origins" overstated it. --- content/trading/swapping-api/agent-attribution.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/trading/swapping-api/agent-attribution.mdx b/content/trading/swapping-api/agent-attribution.mdx index 2b9171c6a..bd12a0031 100644 --- a/content/trading/swapping-api/agent-attribution.mdx +++ b/content/trading/swapping-api/agent-attribution.mdx @@ -55,9 +55,9 @@ Because the request succeeds regardless of whether `X-Agent-Info` parsed, check - **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. The value is always the fixed string `malformed`; it never echoes anything from your request. - **No `x-agent-info-status` header at all** — your `X-Agent-Info` header parsed, or you didn't send one. -The gateway sets this header after it routes your request, and before it writes its own response. Its own error responses carry it too — a 400, a 401, a 403, a 429. So you can debug the header without first getting a working quote. Two cases carry no status header: a 404 for a path the API does not serve, and a CORS preflight. +The gateway sets this header after it routes your request, and before it writes its own response. Error responses carry it too — a 400, a 401, a 403, a 429, and a 404 for a path that does not exist. So you can debug the header without first getting a working quote. The one response that carries no status header is a CORS preflight, which the gateway answers before it looks at `X-Agent-Info`. -Call the Trading API server-to-server. The gateway sends CORS headers only to allow-listed Uniswap origins, so a browser page on your own domain cannot read this header. Check it from a server or with curl. +Call the Trading API server-to-server. The gateway sends CORS headers only to a small allow-list of origins, so a browser page on your own domain cannot read this header. Check it from a server or with curl. ```typescript const response = await fetch('https://trade-api.gateway.uniswap.org/v1/quote', { From c424534af46fd4c7f92ae34ece471fee3faa25ea Mon Sep 17 00:00:00 2001 From: Nick Koutrelakos Date: Tue, 1 Sep 2026 17:28:42 -0700 Subject: [PATCH 7/7] docs(trading): tighten two X-Agent-Info sentences so neither overstates --- content/trading/swapping-api/agent-attribution.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/trading/swapping-api/agent-attribution.mdx b/content/trading/swapping-api/agent-attribution.mdx index bd12a0031..168ad2f67 100644 --- a/content/trading/swapping-api/agent-attribution.mdx +++ b/content/trading/swapping-api/agent-attribution.mdx @@ -36,7 +36,7 @@ curl -X POST https://trade-api.gateway.uniswap.org/v1/quote \ ## What makes a header malformed -A header is dropped (marked malformed) rather than rejected outright if any of the following hold. The request still succeeds either way — see [Confirming it was received](#confirming-it-was-received) below for how to tell the difference. +A header is dropped (marked malformed) rather than rejected outright if any of the following hold. The request is handled exactly as if the header were absent — see [Confirming it was received](#confirming-it-was-received) below for how to tell the difference. - The raw header value is larger than **1024 bytes**, measured on the raw value before parsing. JSON whitespace and `\u` escapes count toward the cap. - The raw header value contains any byte outside printable US-ASCII (`0x20`–`0x7E`). This is checked first, before the JSON is parsed, because bytes above `0x7E` decode differently in different HTTP stacks. So a literal `é`, an emoji, or a curly quote in the header marks it malformed no matter how short the value is. Send non-ASCII as a JSON `\u` escape instead. @@ -55,7 +55,7 @@ Because the request succeeds regardless of whether `X-Agent-Info` parsed, check - **`x-agent-info-status: malformed`** — the header was received but failed one of the checks above and was dropped. The value is always the fixed string `malformed`; it never echoes anything from your request. - **No `x-agent-info-status` header at all** — your `X-Agent-Info` header parsed, or you didn't send one. -The gateway sets this header after it routes your request, and before it writes its own response. Error responses carry it too — a 400, a 401, a 403, a 429, and a 404 for a path that does not exist. So you can debug the header without first getting a working quote. The one response that carries no status header is a CORS preflight, which the gateway answers before it looks at `X-Agent-Info`. +The gateway sets this header after it routes your request, and before it writes its own response. Error responses carry it too — a 400, a 401, a 403, a 429, and a 404 for a path that does not exist. So you can debug the header without first getting a working quote. A CORS preflight carries no status header, because the gateway answers it before it looks at `X-Agent-Info`. Call the Trading API server-to-server. The gateway sends CORS headers only to a small allow-list of origins, so a browser page on your own domain cannot read this header. Check it from a server or with curl.