docs(x402): document error_detail.payment_rejected on the 402 challenge (closes #46, supersedes #45) - #76
Conversation
Issue #46: the 402 x402 challenge contract omitted error_detail.payment_rejected, so generated clients had no way to discover the deny reason on a rejected payment. - Extracted the Error envelopes inner object as the ErrorBody component schema and re-pointed X402PaymentRequired.error_detail at it (allOf + payment_rejected) instead of the wrapped Error schema — the gateway nests the bare error object directly under error_detail with no inner "error" key, confirmed against a live 402 receipt from api.wave.online. Every other Error usage is unchanged (Error still requires "error": ErrorBody). - Documents error_detail.payment_rejected: { reason, rail }, present only when a submitted payment credential was rejected. reason is a stable token (generic token payment_rejected, or a more specific one naming the failing condition); rail names the payment rail that rejected it. Verified against a live rejected- payment receipt. - Regenerated generated/api-types.d.ts from the updated spec (sdk-types CI gate). - CHANGELOG.md: Fixed (error_detail nesting) + Added (payment_rejected) entries. Supersedes #45 (stale branch, conflicts with current main; re-applied by hand). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9mRh8G2ugbUt2kaXvFvF6
|
Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI. |
There was a problem hiding this comment.
Sorry @yakimoto, this account has used its review budget of 2,500,000 diff characters for the last 7 days.
You can request another review in 23 hours and 27 minutes by commenting @sourcery-ai review.
|
ⓘ Qodo reviews are paused because your workspace is out of credits. Ask your workspace admin to add credits to resume reviews. Manage billing |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_ba8635e3-ba6c-4f49-b193-09d9705a10c2) |
Reviewer's GuideUpdates the x402 402 challenge contract to reflect the gateway’s flat Sequence diagram for rejected x402 payment diagnosticssequenceDiagram
participant Client
participant Gateway
Client->>Gateway: GET /v1/clips with X-PAYMENT
Gateway->>Gateway: Validate payment credential
Gateway-->>Client: 402 with error_detail { code, message, payment_rejected }
Note over Client,Gateway: payment_rejected is present only after a submitted payment is rejected
Client->>Client: Read payment_rejected.reason and payment_rejected.rail
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour. 📜 Recent review details⏰ Context from checks skipped due to timeout. (1)
|
| Layer / File(s) | Summary |
|---|---|
Normalized error body schema openapi.yaml |
Adds the reusable ErrorBody schema and changes Error.error to reference it. |
x402 payment rejection details openapi.yaml, CHANGELOG.md |
Changes x402 error_detail to use ErrorBody and adds optional payment_rejected.reason and payment_rejected.rail fields. The changelog documents these updates. |
Estimated code review effort: 2 (Simple) | ~10 minutes
Merge Risk: ⚪ Minimal · up to 530e5
The API contract now documents optional payment-rejection diagnostics while preserving the expected flat 402 error-detail shape. The change is ready to merge.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 inconclusive)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Linked Issues check | ❓ Inconclusive | The PR addresses the core requirement in issue #46 by adding optional error_detail.payment_rejected with required reason and rail fields and correcting the flat ErrorBody path. Full compliance cannot … |
Review the excluded generated/api-types.d.ts and the relevant streaming 402 schema. Confirm that payment_rejected is available at the same path for STREAM_HALTED responses and that the documented reason and rail vocabularies meet issue #46. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Out of Scope Changes check | ✅ Passed | The ErrorBody extraction, x402 schema correction, payment_rejected documentation, generated type regeneration, and changelog update all support the linked issue and stated pull request objectives. No … |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0… |
| Title check | ✅ Passed | The title clearly identifies the main change: documenting error_detail.payment_rejected on the x402 402 challenge. The issue and superseded PR references add useful context. |
| Description check | ✅ Passed | The description directly explains the schema correction, the new payment_rejected field, generated type updates, validation steps, and related issue. |
Full details: Linked Issues check
Explanation
The PR addresses the core requirement in issue #46 by adding optional error_detail.payment_rejected with required reason and rail fields and correcting the flat ErrorBody path. Full compliance cannot be confirmed because generated/api-types.d.ts is excluded by the !/generated/ filter, and the supplied summaries do not verify the required STREAM_HALTED 402 shape or the specified reason and rail vocabularies.
Full details: Out of Scope Changes check
Explanation
The ErrorBody extraction, x402 schema correction, payment_rejected documentation, generated type regeneration, and changelog update all support the linked issue and stated pull request objectives. No unrelated changes are shown.
Full details: Docstring Coverage
Explanation
No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (2 skipped: 2 unsupported.)
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
- Create stacked PR
- Commit on current branch
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Commit unit tests in branch
fix/audit-402-payment-rejected
✨ Simplify code
- Create PR with simplified code
- Commit simplified code in branch
fix/audit-402-payment-rejected
Comment @coderabbitai help to get the list of available commands.
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — The implementation impact is limited to the OpenAPI contract, generated compile-time types, and changelog, with no gateway runtime changes. However, the PR changes the client-visible x402 payment-rejection contract, so its billing/financial implications warrant human review. Not approved because:
Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more. |
|
Note Automatic reviews are paused because your team has used its included automatic processing for this billing period (headroom scales with your seat count). You can still comment "Gitar review" to run one anytime, and automatic reviews resume on their own by October 1. Add seats for more headroom. Code Review ✅ ApprovedAligns the x402 payment-required schema with the gateway's live error responses by correcting OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
…t_rejected entry, keep link refs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9mRh8G2ugbUt2kaXvFvF6
…sed/Fixed, not under 1.0.0 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K9mRh8G2ugbUt2kaXvFvF6
Breaking: yes
Breaking: yes — acknowledged on purpose.
oasdiffflags theX402PaymentRequired.error_detailshape change (previously$ref: Error, an{ error: {...} }wrapper; nowallOf: [ErrorBody, { payment_rejected }], the flat object). The wire did not change: the live gateway has always returned the flat body — receiptcurl -s https://api.wave.online/v1/clips | python3 -c 'import sys,json;print(list(json.load(sys.stdin)["error_detail"].keys()))'→['code','message','session_id','suggestions','doc_url','next_action'](noerrorwrapper). The spec was wrong, the API is unchanged; any generated client that trusted the old shape was already failing to readerror_detail. Only the contract document moves.Motivation
Issue #46 (OPEN): the 402 x402 challenge contract omits
error_detail.payment_rejected, so generated clients cannot discover the deny reason on a rejected payment. Confirmed onorigin/mainbefore this change:git -C ~/wave-av/api-spec grep -n "payment_rejected" origin/main -- openapi.yamlreturned no hits, while the gateway (wave-gatewaysrc/x402-envelope.ts) publisheserror_detail.payment_rejected: { reason, rail }on every 402 that follows a rejected payment.An earlier PR (#45, branch
docs/x402-payment-rejected-field, 2026-08-12) documented this but now conflicts withorigin/main. This PR re-applies the same documentation by hand on top of currentmainand supersedes #45 (do not merge #45).Root cause / what changed
While verifying the field against a live receipt, the base
error_detailschema was also found to be wrong: it$ref'd theErrorenvelope ({ error: { code, message, ... } }), but the gateway nests the bare error object directly undererror_detail— no innererrorwrapper. Documentingpayment_rejectedcorrectly required fixing this first, or the new field would sit at the wrong JSON path in generated types.openapi.yaml:Errorenvelope's inner object as a newErrorBodycomponent schema.Error.errornow$refsErrorBody— every one of the other 21$ref: '#/components/schemas/Error'usages in the spec is unchanged (still requireserror: ErrorBody).X402PaymentRequired.error_detailnow composesallOf: [ErrorBody, { payment_rejected }]instead of$ref: Error, matching the live wire shape (flat object, noerrorwrapper).error_detail.payment_rejected: { reason: string, rail: string }(both required when the object is present), documented as present only when a submitted payment credential was rejected.reasonis a stable token — the generic fallback ispayment_rejected; more specific tokens name the failing condition (e.g.invalid_permit_header,session_expired,duplicate,rate_limited).railnames the payment rail that rejected it.generated/api-types.d.tsregenerated from the updated spec (thesdk-typesCI gate fails on drift).CHANGELOG.md:Fixedentry for theerror_detailnesting bug,Addedentry forpayment_rejected(closes #46).Live receipts
Unauthenticated challenge (no payment_rejected, as expected):
Confirms
error_detailis a FLAT object (code/message/session_id/suggestions/doc_url siblings) — never wrapped under anerrorkey. This is what motivated theErrorBodyextraction above.Rejected payment (malformed credential):
Confirms the exact shape now documented:
error_detail.payment_rejected: { reason, rail }, both strings, sibling tocode/message/suggestions/doc_url.Gates run (this branch, off
origin/main)redocly lint openapi.yaml(2.40.0) — valid, 55 warnings (identical count toorigin/mainbaseline — zero new warnings/errors introduced):node .github/scripts/assert-refs.mjs openapi.yaml(mirrors thespec-lintCI job):openapi-typescript@7.13.0 openapi.yaml -o generated/api-types.d.ts(mirrors thesdk-typesCI job) — succeeded, pre-existing warnings only (unused components, missing 4xx on unrelated operations — unchanged by this PR); regenerated file is committed so CI'sgit diff --exit-codestep is clean.Generated type spot-check confirms the fix:
Operator steps
None. No secrets, no infra, no deploy — spec-only change.
Closes #46. Supersedes #45 — the old branch is stale and conflicts with
origin/main; do not merge it.🤖 Generated with Claude Code
https://claude.ai/code/session_01K9mRh8G2ugbUt2kaXvFvF6
Note
Low Risk
Spec and generated types only; no gateway or runtime behavior changes. SDK consumers may need to stop reading
error_detail.errorin favor of flatcode/message, which matches production wire format.Overview
Aligns the OpenAPI contract for HTTP 402 x402 challenges with what the gateway actually returns, and documents rejection diagnostics for paying clients.
error_detailshape fix: The spec previously pointedX402PaymentRequired.error_detailat the fullErrorenvelope ({ error: { code, message, ... } }), but live 402 bodies put the normalized error object flat undererror_detail(no innererrorkey). This PR extracts that inner object as a reusableErrorBodyschema (Error.errornow$refs it; otherErrorresponses are unchanged) and modelserror_detailasErrorBodyinstead, sogenerated/api-types.d.tsno longer implies a boguserror_detail.errorpath.Rejected-payment field:
error_detailis extended (viaallOf) with optionalpayment_rejected: { reason, rail }, present only when a submitted payment was denied—not on a plain unpaid challenge.CHANGELOG.mdrecords both the nesting fix and the new field (closes #46).Reviewed by Cursor Bugbot for commit 530e54d. Bugbot is set up for automated code reviews on this repo. Configure here.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by Sourcery
Align the x402 payment-required schema and generated types with the gateway’s live error responses, including rejected-payment diagnostics.
New Features:
X402PaymentRequired.error_detail.payment_rejecteddenial details, including the rejection reason and payment rail.Bug Fixes:
error_detailschema to model the gateway’s flat error object instead of incorrectly requiring an innererrorenvelope.Enhancements:
ErrorBodyschema while preserving the existingErrorenvelope for other responses.Documentation:
Chores: