docs: clarify fiat vs crypto payments and fix stale x402 token examples#226
Conversation
Addresses hackathon feedback in nvm-monorepo#1076 — subscribers can't tell a plan's payment type (fiat vs crypto) upfront and get blocked when they lack the required method. Correctness — the buyer-side getX402AccessToken / get_x402_access_token call now requires a create-first delegationConfig (bare 2-arg calls throw or are rejected). Update the stale examples to create a delegation first, then mint the token by delegationId, across query-agents, process-requests, the quickstarts, langchain, express, fastapi, agentcore, strands, the google-a2a / mcp / x402-ap2 integration guides, and the app overview. Clarity (fiat vs crypto): - order-plans: add "Which payment type does this plan need?" with resolveScheme / resolve_scheme detection. - core-concepts: add a fiat-vs-crypto prerequisites comparison table. - nevermined-x402: correct the buyer-side Note — the direct token call does NOT auto-detect; it defaults to nvm:erc4337. Middleware / A2A clients do. - integration-faq: add a payment-method-mismatch troubleshooting entry. - card-enrollment / card-delegation: add provider detection via resolveNetwork / resolve_network before enrolling. Skill references under skills/nevermined-payments/ already use the correct create-first pattern and were left unchanged. api-reference/ is generated and untouched. Verified with mintlify broken-links and mintlify validate.
There was a problem hiding this comment.
Pull request overview
Updates Nevermined documentation to (1) fix stale/non-runnable x402 buyer-token examples by adopting the delegation-first flow, and (2) clarify up-front whether a plan requires fiat (card) or crypto, including how to detect the correct scheme/provider via SDK helpers.
Changes:
- Replaced direct
getX402AccessToken/get_x402_access_tokenexamples with “create delegation first, then mint token bydelegationId” patterns across guides and integrations. - Added/expanded fiat-vs-crypto guidance (tables, notes, troubleshooting) and documented scheme/provider detection with
resolveScheme/resolve_schemeandresolveNetwork/resolve_network. - Updated integration docs (MCP, A2A, framework examples) to reflect the corrected token/delegation flow and scheme defaults.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/solutions/card-delegation.mdx | Clarifies that the enrollment provider must match the plan; links to provider detection guidance. |
| docs/products/payments/card-enrollment.mdx | Adds resolveNetwork / resolve_network snippet to determine the correct card provider before enrolling. |
| docs/products/nevermined-app/overview.mdx | Updates the SDK integration snippet to use delegation-first token minting (but currently has undefined variables; see comment). |
| docs/integrations/nevermined-x402-ap2.mdx | Fixes Python subscriber token example to use create-delegation-first + delegation_id. |
| docs/integrations/mcp.mdx | Updates subscriber token minting example to include delegation creation and pass delegationId. |
| docs/integrations/google-a2a.mdx | Adds note about fiat vs crypto handling and updates TypeScript token example to delegation-first. |
| docs/integrate/quickstart/python.mdx | Fixes quickstart buyer flow to create delegation first and mint token with X402TokenOptions. |
| docs/integrate/add-to-your-agent/strands.mdx | Updates client example to create delegation first and pass delegation config when minting tokens. |
| docs/integrate/add-to-your-agent/langchain.mdx | Updates both TS/Python client snippets to the delegation-first token flow. |
| docs/integrate/add-to-your-agent/fastapi.mdx | Fixes Python client example to create delegation first and pass explicit scheme + delegation id. |
| docs/integrate/add-to-your-agent/express.mdx | Fixes TypeScript client example to create delegation first and pass scheme + delegationId. |
| docs/integrate/add-to-your-agent/agentcore.mdx | Updates Python client snippet to include delegation-first token minting and cleans up imports. |
| docs/getting-started/quickstart.mdx | Updates subscriber SDK examples (Python) to use delegation-first token minting; adds fiat option comments. |
| docs/getting-started/core-concepts.mdx | Adds a fiat-vs-crypto prerequisites table and points readers to scheme detection guidance. |
| docs/getting-started/ai-agent-purchase.mdx | Clarifies that plans are strictly fiat or crypto and links to detection section. |
| docs/development-guide/query-agents.mdx | Reworks buyer-token section to explain delegations and updates TS/Python snippets accordingly. |
| docs/development-guide/process-requests.mdx | Adds delegation-first note and updates TS/Python examples to mint tokens against delegationId. |
| docs/development-guide/order-plans.mdx | Adds “Which payment type…” section with resolveScheme / resolve_scheme and scheme-default clarification. |
| docs/development-guide/nevermined-x402.mdx | Corrects guidance: direct buyer token minting does not auto-detect scheme; middleware/A2A do. |
| docs/development-guide/integration-faq.mdx | Adds troubleshooting table mapping common mismatch errors to concrete fixes. |
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
…iew snippet - order-plans: import resolve_scheme from payments_py.x402.resolve_scheme (submodule path, consistent with the x402 api-reference and resolve_network) - nevermined-app/overview: define agentId/planId so the SDK snippet is copy/paste runnable (was referencing undefined planId/agentId)
r-marques
left a comment
There was a problem hiding this comment.
🤖 Automated PR review — ✅ Ready to merge
Reviewed origin/main...HEAD (20 files) with the pr-review-toolkit panel: docs-quality reviewer + two dedicated fact-checkers (SDK API accuracy against @nevermined-io/payments / payments_py, and error-code + internal-link integrity against nvm-monorepo + the docs tree).
This is a documentation-only PR whose value rests entirely on the factual accuracy of its SDK examples, error codes, and cross-links. All three were verified against source — and they hold up. No blockers, no should-fix items; a few optional polish nits below.
Verification performed (all ✅)
- Every SDK signature in the diff is real and copy-paste-safe. The central claim —
getX402AccessToken/get_x402_access_tokendefault tonvm:erc4337and do not auto-detect the scheme — is confirmed (payments/src/x402/token.ts:69,payments-py/payments_py/x402/token.py:177).createDelegation/create_delegationfield names, thedelegationConfig/schemetoken options, theresolveScheme/resolveNetwork(+ Pythonresolve_scheme/resolve_network) exports, and theX402TokenOptions/DelegationConfig/CreateDelegationPayloadimport paths all match the current SDK source. The "create a delegation first, then mint against it" narrative is exactly the SDK's now-preferred path (the old inline form emits aFutureWarning). - Both troubleshooting error codes are real — verified against
origin/main(note: they are recently added; a stale local checkout won't have them, butorigin/maindoes):BCK.X402.0027—api-errors.ts:1410("Payment method not found or unusable"), thrown atapps/api/src/x402/handlers/card-delegation-scheme.handler.ts:219with the literal message "No accessible payment method found for this API Key" — matching the FAQ's paraphrase.BCK.PROTOCOL.0050—api-errors.ts:1212("Fiat plans cannot be ordered through this endpoint. Use the x402 card-delegation settle flow (POST /api/v1/x402/settle)…"), and it is thrown for fiat plans on the order path (apps/api/src/protocol/protocol.service.ts:1223, covered byprotocol.service.fiat-rejection.spec.ts). The FAQ's "useorderFiatPlan()/POST /api/v1/x402/settle" guidance is correct.
- Plan-type source verified:
registry.price.isCrypto(ContractsTypes.ts:36) andmetadata.plan.fiatPaymentProvider(DDOTypes.ts:77) both exist. - All 7 internal cross-links/anchors resolve, including the ones that looked risky:
card-enrollment#choosing-a-provider(heading "## Choosing a Provider" at line 194),/docs/products/payments/mandates, andtop-up#when-top-ups-stop. - Style/terminology on-spec: second person, active voice, "plan" (never "subscription"),
payment-signatureheader, x402 v2 schemes, no legacyisValidRequest, nostaging_*environment names. The repeated delegation snippet is consistent (same field names/comments/values) across TS and Python in all files.
🔴 Blockers (0)
None.
🟡 Should fix (0)
None.
💡 Good to have (4, all optional)
- Mixed
schemeinclusion across the new delegation examples. Four examples passschemeexplicitly (express.mdx,fastapi.mdx,quickstart.mdx,integrate/quickstart/python.mdx) while the rest omit it. Functionally fine (nvm:erc4337is the default), but a reader copying two adjacent guides sees the call shaped differently for no stated reason. Consider standardising on the express/fastapi style — the commentedscheme: 'nvm:erc4337', // 'nvm:card-delegation' for fiat plansline is the single best in-context reminder of the fiat path. (docs-quality, confidence 75) docs/development-guide/integration-faq.mdxstill has no trailing newline (the edit appends content but leaves\ No newline at end of file). Harmless to Mintlify; worth adding while the file is open to keep future diffs clean. (docs-quality, confidence 80)process-requests.mdxis the one page in the set that doesn't get the closing "detect a plan's type →order-plans#which-payment-type-does-this-plan-need" pointer the others received. It already links there in its top<Note>, so this is purely about making the set fully parallel. (docs-quality, confidence 60)resolveNetwork/fiatPaymentProvidertyping nuance.resolveNetwork()actually returnsstring | undefined(the rawfiatPaymentProvidervalue), not a constrained'stripe' | 'braintree' | 'visa'union — the documented values are correct in practice but not type-enforced. Separately, the backendDDOTypes.fiatPaymentProviderenumerates only'stripe' | 'braintree'while the docs (and the SDK delegationproviderunion) include'visa'; likely just a backend type lag, but worth a quick confirm thatvisaflows throughfiatPaymentProviderthe same way. (api-accuracy, confidence 60)
✅ Strengths
- Fixes a genuinely misleading stale example. The old
getX402AccessToken(planId, agentId)one-liner silently defaulted to crypto; the new "create a delegation first, then mint against it" flow matches the SDK's current preferred path and prevents the exact fiat-vs-crypto mismatch the PR sets out to clarify. - Accurate, actionable troubleshooting. The new FAQ maps real, recently-added backend error codes to concrete fixes — the kind of problem-aware, practical content the repo's style guide asks for.
- Strong cross-file consistency and terminology discipline, with clean comparison tables in
core-concepts.mdxandorder-plans.mdxand correct Mintlify component usage throughout.
…line - Add the commented `scheme: 'nvm:erc4337' // 'nvm:card-delegation' for fiat` reminder to the buyer-token examples that omitted it (query-agents, process-requests, langchain, agentcore, strands, google-a2a, mcp, app overview), matching the express/fastapi style so the fiat path is signalled uniformly at the token call. - integration-faq: add trailing newline. Left pre-existing canonical examples (top-up, x402-facilitator, products/ payments/overview, mandate-selection) as-is to keep the PR scoped.
|
Thanks for the thorough fact-check — addressed the optional nits in e7f5172:
|
Summary
Refreshes the docs to address hackathon feedback in nevermined-io/nvm-monorepo#1076 — "subscribers can't tell whether a plan is fiat or crypto upfront, and get blocked when they lack the required payment method."
The review found the issue partially addressed: the SDK primitives now exist (
resolveScheme/resolve_scheme, dedicated error codes), but the buyer-facing docs over-claimed scheme auto-detection and contained stale, non-runnable token examples. This PR fixes two problems.1. Correctness — stale x402 buyer-token examples
The direct
getX402AccessToken/get_x402_access_tokencall now requires a create-firstdelegationConfig(TS throws locally; Python is rejected by the backend). 24 examples still used the bare two-arg form, so they don't run. Updated them to create a delegation first, then mint the token bydelegationId:query-agents,process-requestsgetting-started/quickstart(Python),integrate/quickstart/pythonlangchain(×4),express,fastapi,agentcore,strandsgoogle-a2a,mcp,nevermined-x402-ap2products/nevermined-app/overview2. Clarity — fiat vs crypto
order-plans— new "Which payment type does this plan need?" section withresolveScheme/resolve_schemedetection.core-concepts— side-by-side fiat-vs-crypto prerequisites table.nevermined-x402— corrected the buyer-side Note: the direct token call does not auto-detect the scheme (defaults tonvm:erc4337); middleware and A2A clients do.integration-faq— payment-method-mismatch troubleshooting (mapsBCK.X402.0027,BCK.PROTOCOL.0050, and "No enrolled card found" to fixes).card-enrollment/card-delegation— detect the required provider withresolveNetwork/resolve_networkbefore enrolling.Status of issue #1076's proposals
isCryptois a single boolean — a plan is strictly one typeThe docs/SDK-facing portion is addressed by this PR; remaining items (#2/#3/#4) are product/UX/protocol work, tracked via a status comment on #1076.
Not changed
docs/api-reference/**— generated/mirrored from the SDK repos.skills/nevermined-payments/**— already uses the correct create-first pattern.Test plan
mintlify broken-links— no broken links foundmintlify validate— build validation passedorigin/mainofpayments/payments-py(import paths, arg order,delegationConfig, fiatscheme)🤖 Generated with Claude Code