Skip to content

docs: quote requests with a referrer require an API key - #451

Merged
pedromcunha merged 2 commits into
mainfrom
docs/quote-referrer-api-key
Sep 9, 2026
Merged

docs: quote requests with a referrer require an API key#451
pedromcunha merged 2 commits into
mainfrom
docs/quote-referrer-api-key

Conversation

@GiselleNessi

Copy link
Copy Markdown
Collaborator

Documents the quote authentication change that went live on 2026-09-03 (INT2-1418): POST /quote and POST /quote/v2 requests that include a referrer now require a valid x-api-key header and return 401 / UNAUTHORIZED_QUOTE without one.

Closes the docs portion of INT2-1384.

Changes

  • references/api/changelog.mdx: new 2026-09-03 Breaking entry (includes the SDK note, since the SDK sets referrer automatically)
  • references/api/api_core_concepts/handling-errors.mdx: adds the UNAUTHORIZED_QUOTE row to the error table
  • references/api/api-keys.mdx: adds a Warning callout under How to Use an API key

Reviewer note (Pedro/Ted): please confirm whether any valid key satisfies the check, or whether the key must belong to the organization that owns the referrer. Our testing suggests the latter (a valid key with a different org's referrer still returns 401). If binding is enforced, the changelog line should say "the API key of the organization that owns the referrer" instead of "a valid x-api-key".

Context: integrators (Cronos, VVS) hit this via 401s today — Pylon 7784.

Adds the 2026-09-03 changelog entry, the UNAUTHORIZED_QUOTE error code
row, and an authentication callout on the API keys page. Covers the
enforcement shipped in INT2-1418 (INT2-1384).
@mintlify

mintlify Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
unevenlabs 🟢 Ready View Preview Sep 9, 2026, 9:12 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 3m 38s —— View job


Code review — PR #451

  • Read the diff against origin/main
  • Check changed pages against AGENTS.md style rules
  • Check changelog entry shape / generator compatibility
  • Post review

The three edits are well-targeted and the changelog entry is mechanically correct (heading matches the /^## (\d{4}-\d{2}-\d{2})\s*—\s*(.+)$/ parser at scripts/build-changelog.mjs:181, newest-first ordering is right, and the unified changelog.mdx is correctly left alone for the hourly sync per AGENTS.md §4.6). What's missing is the §4.2 "update inbound surfaces in the same PR" half — one existing example is now broken by this change.


1. refunds.mdx documents a POST /quote/v2 call that now returns 401

references/api/api_core_concepts/refunds.mdx:52 — "You can force a refund by passing debug-force-refund as the referrer", followed by a copy-paste curl that sends "referrer": "debug-force-refund" with only Content-Type and no x-api-key:

curl -X POST 'https://api.relay.link/quote/v2' \
  -H 'Content-Type: application/json' \
  -d '{ "referrer": "debug-force-refund", ... }'

Anyone following that testing recipe as of 2026-09-03 gets 401 / UNAUTHORIZED_QUOTE — the exact failure this PR exists to document. This is the one inbound surface in the repo that actually breaks, and it should be fixed in the same PR (§4.2, "Update inbound links"). Fix this →

It also sharpens your reviewer question for Pedro/Ted: if the key must belong to the org that owns the referrer, then debug-force-refund is a magic referrer no key can own, and that debug flow is dead rather than just needing a header. Worth asking alongside the binding question.

2. The changelog's SDK migration advice contradicts this repo's own key guidance

references/api/changelog.mdx:18 tells SDK integrations to "configure apiKey on createClient or pass the key per call via the headers parameter." For browser integrations that's advice this repo explicitly warns against, on the page the same sentence links to:

  • references/api/api-keys.mdx:85// Set apiKey only when using the SDK server-side.
  • references/api/api-keys.mdx:137 — "Keep it server-side only — never expose it in client-side or frontend code."

Since the SDK is heavily used client-side (the swap widget, the hooks), the migration path for those integrators is the proxy API, not apiKey on createClient. One clause pointing at #proxy-api for browser callers would keep the entry from sending readers into a leaked-key pattern. Fix this →

3. "the Relay SDK sets referrer automatically" — name source, and check the unset case

The knob readers recognize is source, documented as optional at references/relay-kit/sdk/createClient.mdx:15 ("The source to associate your onchain activity with, should map to a domain", Required ❌). The SDK sends it as the request referrer. So the blast radius is probably "SDK clients that set source", not all SDK clients — worth confirming with the SDK owner whether a client with no source sends no referrer and stays unaffected. If it is source-gated, saying so narrows the change from "every SDK integration" to a checkable condition.

Either way createClient.mdx is where someone configures source and never learns it now implies an API key. A one-line addition to that row or a short <Info> under the table would catch them at the point of configuration. Fix this →

4. "at the public rate limit" is an undefined term — on the rate-limits page

references/api/api-keys.mdx:69 ends with "Unauthenticated quote requests are supported only without a referrer, at the public rate limit." Nothing in the docs defines a public/unauthenticated limit: the two tables on this page are both introduced as "per API key" (:34, :45), and handling-rate-limits.mdx doesn't mention one either. A reader who hits the phrase on the page whose whole job is rate limits has nowhere to go. Either give the number or drop the clause. Fix this →

5. The quote endpoint pages carry no note

references/api/get-quote.mdx and get-quote-v2.mdx are bare OpenAPI stubs. A conditional auth requirement ("required only when the body contains referrer") is precisely the kind of thing AGENTS.md §3.3 keeps body content for — a cross-cutting note the spec can't express — and the endpoint reference is where a reader debugging a 401 actually lands. A one-line <Note> on each, phrased as current behavior rather than as change history (§4.2 keeps the change narrative in the changelog), would close the loop. Fix this →

Nits

  • Prose parameter formatting (§2.9). The changelog line mixes conventions inside one paragraph: `referrer` and `headers` plain, but apiKey bold+backticks. §2.9 asks for bold+backticks on prose parameter references — pick one and apply it to all three.
  • Paragraph length (§2.10). That **Breaking** paragraph runs five sentences. The migration guidance (SDK + dashboard) reads better as its own paragraph, the way the 2026-09-05 entry splits out **Replacement**. Renders identically under Breaking if you leave it unled — splitChangeTypes() appends a lead-less paragraph to the change above it (scripts/build-changelog.mjs:227).
  • Pending the org-binding answer, the handling-errors.mdx row wording ("no valid x-api-key header") would also need to change to something like "the API key does not own the referrer" — the error table is easy to forget when you revise the changelog line.
  • Unrelated, spotted nearby: references/relay-kit/sdk/createClient.mdx:18 gives maxPollingAttemptsBeforeTimeout a copy-pasted source description. Pre-existing; worth a separate one-liner PR.

Nothing here blocks the intent of the PR — finding 1 is the only hard breakage, and it's a two-line fix.
· branch docs/quote-referrer-api-key

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @GiselleNessi's task in 2m 40s —— View job


Code review

  • Read PR diff and gather context
  • Check changed pages against AGENTS.md (§2, §3.3, §4.2, §4.5, §4.6)
  • Verify factual claims (SDK apiKey/headers, error table, links, changelog parser)
  • Post review

Three files, all additive, and the mechanics are right: the changelog heading matches the ## YYYY-MM-DD — <summary> shape scripts/build-changelog.mjs:181 parses, entries stay newest-first, the generated root changelog.mdx is correctly left alone (§4.6), the error row is in alphabetical position, and the callout is well under the 15-line cap (§2.5). Findings below, most significant first.


1. Client-side SDK integrations are left without a valid path — and the advice contradicts existing SDK docs

references/api/changelog.mdx:18 tells SDK integrators to "configure apiKey on createClient or pass the key per call via the headers parameter." Both of those are documented as server-only:

  • references/relay-kit/sdk/createClient.mdx:13apiKey: "Only pass in this property when the Relay client instance is used exclusively server-side. Otherwise you'll leak your key to the client."
  • references/relay-kit/sdk/actions/getQuote.mdx:15 — "Never pass x-api-key in headers from client-side code."

If the SDK sets referrer automatically, as the entry states, then every browser SDK integration now needs a key on /quote and neither suggested remedy is permissible for them. The remedy that is — baseApiUrl pointed at a proxy that injects x-api-key, the pattern already documented at references/api/api-keys.mdx:111 and prescribed on useRequests.mdx:8 / ui/installation.mdx:82 — is missing from both the changelog entry and the new Warning. The Warning is especially worth fixing since the Proxy API section is 40 lines below it on the same page.

Fix this →

2. "the public rate limit" is not a documented thing

Both new passages (api-keys.mdx:69, changelog.mdx:18) end by pointing at "the public rate limit," but nothing in the docs defines one. api-keys.mdx:34 says "The following limits apply per API key," and Elevated Rate Limits is also per-key — a reader who follows the Warning up the page finds no unauthenticated limit. Either add a row/line for it under Default Rate Limits, or drop the phrase and just say referrer-less requests still work without a key.

3. The quote endpoint reference pages say nothing about the new 401

references/api/get-quote-v2.mdx and references/api/get-quote.mdx are bare stubs. A new conditional auth requirement is exactly the "cross-cutting note that OpenAPI can't express" that §3.3 sanctions a short <Note> for, and the endpoint page is where someone hand-building a /quote call actually lands — more likely than the API keys page. A one-liner on both, pointing to /references/api/api-keys#how-to-use-an-api-key, would close the biggest discovery gap. (Worth confirming whether the spec itself now documents the 401; if so this may be redundant on /quote/v2.)

4. The org-binding question affects three strings, not one

Your reviewer note scopes the open question to the changelog line, but "no valid x-api-key" is now asserted in handling-errors.mdx:42 and api-keys.mdx:69 as well. If the key must belong to the referrer's organization, all three need the narrower wording — and UNAUTHORIZED_QUOTE becomes a code an integrator can hit with a valid key, which is worth stating explicitly on the error row.

5. Changelog entry packs the migration note into the **Breaking** paragraph

§4.5 puts each change-type lead on its own line, and the sibling entries in this file split follow-up guidance out (**Replacement** at lines 14 and 24). Here the SDK migration — the part most readers need — is sentence four of five in a single block, against §2.10's 2–3 sentence cap. Suggest lifting it to its own bolded lead (**Migration** —) with the proxy option from finding 1.

Minor, same entry: referrer is plain-backticked while apiKey is bold-backticked in the same sentence. §2.9 wants param in prose, the rest of this file uses plain backticks — either is defensible, but not both in one line.

6. Nits

  • handling-errors.mdx:42 — sibling rows that have a fix path link out (INVALID_GAS_LIMIT_FOR_DEPOSIT_SPECIFIED_TXS, SOLANA_TX_TOO_LARGE). This row could link /references/api/api-keys#how-to-use-an-api-key.
  • §4.2 says "No inline <Warning> callout on the updated page," with an <Info> + date + changelog pointer as the exception. The new callout reads as steady-state behavior rather than a change notice, so I think it's the right call to keep it — but it's a <Warning> on a page describing a changed surface, so worth a deliberate decision rather than an accidental one.

I did not run node scripts/build-changelog.mjs --check — it needs a full clone of relay-kit, and per §4.6 a source-only PR is expected to preview without the entry until merge, so a failure there wouldn't be meaningful.

No changes committed — this is review feedback only.
· docs/quote-referrer-api-key

@greptile-apps

greptile-apps Bot commented Sep 9, 2026

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge because no blocking failure remains within the scope of this follow-up review.

Summary

  • Adds a warning to the API-key guide covering POST /quote and POST /quote/v2.
  • Documents the 401 / UNAUTHORIZED_QUOTE response in the quote error reference.
  • Records the breaking change and SDK configuration implications in the API changelog.

ipeleg
ipeleg previously approved these changes Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Claude finished @GiselleNessi's task in 2m 36s —— View job


Code review — PR #451

  • Read the diff against origin/main
  • Check changed pages against AGENTS.md (§2, §3.3, §4.2, §4.5, §4.6)
  • Verify claims against the repo (createClient, getQuote, api-keys, changelog parser)
  • Post review

Re-reviewed at 51f76aa. The mechanics hold up: the heading matches the /^## (\d{4}-\d{2}-\d{2})\s*—\s*(.+)$/ parser at scripts/build-changelog.mjs:181, entries stay newest-first (09-08 → 09-05 → 09-03 → 09-01), the generated root changelog.mdx is correctly untouched (§4.6), the error row is in alphabetical position, and the callout is 3 lines — well under the §2.5 cap. The "public rate limit" clause flagged earlier is gone in 51f76aa; that one's closed.

What's still open is the §4.2 half of the job — updating inbound surfaces in the same PR. One page in the repo is now factually broken by this change, and the migration advice points browser integrators at a pattern this repo tells them never to use.


1. refunds.mdx ships a POST /quote/v2 recipe that now returns 401

references/api/api_core_concepts/refunds.mdx:51-69 — "How can I force a refund for testing purposes?" → "pass debug-force-refund as the referrer", followed by a copy-paste curl that sends "referrer": "debug-force-refund" with Content-Type as its only header:

curl -X POST 'https://api.relay.link/quote/v2' \
  -H 'Content-Type: application/json' \
  -d '{ "referrer": "debug-force-refund", ... }'

As of 2026-09-03 that returns 401 / UNAUTHORIZED_QUOTE — the exact failure this PR documents. I grepped every referrer occurrence in .mdx; this is the only request example in the repo that sets one, so it's the whole inbound-link surface and it's a two-line fix. (deposit-addresses.mdx:1244 is a response payload, not a request — unaffected.)

It also sharpens your reviewer question: if the key must belong to the org owning the referrer, debug-force-refund is a magic referrer no key can own, and that debug flow is dead rather than just needing a header. Worth asking Pedro/Ted alongside the binding question.

Fix this →

2. Both new passages give browser SDK integrators the one remedy this repo forbids

changelog.mdx:18 — "SDK integrations must configure apiKey on createClient or pass the key per call via the headers parameter." api-keys.mdx:69 — "pass your API key in the x-api-key header."

Both options are documented as server-only, in this repo:

  • references/relay-kit/sdk/createClient.mdx:13apiKey: "Only pass in this property when the Relay client instance is used exclusively server-side. Otherwise you'll leak your key to the client."
  • references/relay-kit/sdk/actions/getQuote.mdx:15 — "Never pass x-api-key in headers from client-side code."
  • references/api/api-keys.mdx:137 — "never expose it in client-side or frontend code."

If the SDK sets referrer automatically (as the entry states), every browser SDK integration — the widget, the hooks — now needs auth on /quote, and neither suggested remedy is permissible for them. The one that is — baseApiUrl pointed at a proxy — is documented 42 lines below the new Warning at api-keys.mdx:111, and the Warning doesn't mention it. A clause pointing client-side callers at #proxy-api in both places keeps the entry from routing readers into a leaked-key pattern.

Fix this →

3. "the Relay SDK sets referrer automatically" — the knob is source, and it's optional

The SDK sends source as the request referrer, and source is optional: references/relay-kit/sdk/createClient.mdx:15 (Required ❌, "The source to associate your onchain activity with"). So the blast radius is probably "SDK clients that set source", not all of them. Worth confirming with the SDK owner whether a client with no source sends no referrer and stays unaffected — if it's source-gated, saying so turns "every SDK integration" into a condition an integrator can check in one glance at their createClient call.

Either way, createClient.mdx is where someone configures source and never learns it now implies an API key — and features/fast-fill.mdx:56 and references/relay-kit/sdk/installation.mdx:41 both ship source: in their examples. One line on that table row, or a short <Info> under it, catches them at the point of configuration.

Fix this →

4. The quote endpoint pages still say nothing

references/api/get-quote.mdx and get-quote-v2.mdx are bare four-line stubs. A conditional auth requirement — "required only when the body contains referrer" — is exactly the "cross-cutting note that OpenAPI can't express" §3.3 reserves body content for, and the endpoint reference is where someone hand-building a /quote call and debugging a 401 actually lands, ahead of the API keys page. A one-line <Note> on each, phrased as current behavior rather than change history (§4.2 keeps the narrative in the changelog), closes the discovery gap. Worth checking whether the OpenAPI spec now documents the 401 itself — if so this may be redundant on /quote/v2.

Fix this →

5. The error row lands on a page scoped to /quote/v2

handling-errors.mdx:6 opens "When calling the /quote/v2 endpoint…", but your changelog line says UNAUTHORIZED_QUOTE applies to POST /quote too. A legacy /quote caller who hits the 401 has no reason to trust this table covers them. Either widen the intro to "/quote and /quote/v2" or say so on the row.

6. The org-binding question touches three strings, not one

Your reviewer note scopes the open question to the changelog line, but "no valid x-api-key" is now asserted in handling-errors.mdx:42 and api-keys.mdx:69 as well. If the key must belong to the referrer's org, all three need the narrower wording — and UNAUTHORIZED_QUOTE becomes a code you can hit with a valid key, which is worth stating on the error row explicitly. Easy to revise the changelog and forget the other two.

Nits

  • §2.10 paragraph length. The **Breaking** paragraph is four sentences. The sibling entries split follow-up guidance into their own lead (**Replacement** at lines 14 and 24); lifting the migration guidance to **Migration** — matches §4.5 and puts the part most readers need at the top of its own block. A lead-less paragraph would also work — splitChangeTypes() appends it to the change above (scripts/build-changelog.mjs:227) — but a named lead reads better here.
  • §2.9 mixed conventions. One sentence has `referrer` and `headers` plain but apiKey bold+backticked. §2.9 wants bold+backticks in prose; the rest of this file uses plain. Either is defensible — not both in one line.
  • §4.2 <Warning> exception. §4.2 says no inline <Warning> on the page describing a changed surface. The new callout is on api-keys.mdx, not the endpoint page, and reads as steady-state behavior, so I think it's the right call — flagging it as a deliberate decision rather than an accidental one.
  • Pre-existing, spotted nearby: references/relay-kit/sdk/createClient.mdx:18 gives maxPollingAttemptsBeforeTimeout a copy-pasted source description. Worth a separate one-liner PR.

I did not run node scripts/build-changelog.mjs --check — it needs a full clone of relay-kit, and per §4.6 a source-only PR is expected to preview without the entry until merge, so a failure there wouldn't be meaningful. Nothing here blocks the intent of the PR; finding 1 is the only hard breakage.

No changes committed — review feedback only.
· branch docs/quote-referrer-api-key

@pedromcunha
pedromcunha merged commit f77e831 into main Sep 9, 2026
5 checks passed
@pedromcunha
pedromcunha deleted the docs/quote-referrer-api-key branch September 9, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants