0.6.1: parse production error bodies, sync OpenAPI 3.30.0, fail on malformed WS frames - #13
Merged
Conversation
…; add AGENTS.md README: CreateV2 example was missing the required self_trade_prevention_type; APIError description overstated what decodes from production bodies; the not-implemented list omitted several paths and four optional filters; retry section now states the Retry-After cap and the 409-on-replay behavior; WS section covers private channels, subscription-scoped error frames, the AsyncAPI host, and server pings. CHANGELOG 0.6.0 heading narrowed to what the change actually guarantees. Example README no longer claims LIVE=1 forces production. AGENTS.md is the committed, tool-neutral contributor guide: layout, spec sync, conventions, mandatory tests, CI version rules, spec-vs-production notes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
types.ErrorResponse follows the spec's flat {"code","message","details"},
but production wraps most errors as {"error":{"code":...,"message":...}}
and parameter-binding 400s as {"msg":"..."}. Every *APIError from the live
API therefore had empty Code/Message and Error() printed only the status.
newAPIError now decodes all three shapes; the flat form wins when present.
RawBody is unchanged. Tests use the bodies observed from production.
Fixes #7
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ilters Vendored specs refreshed from docs.kalshi.com. 3.30.0 adds Series.categories (the full discovery list the category filter matches against) and GetTargetBalanceAllocationResponse.resting_margin_reservation; both added with unmarshal tests. The AsyncAPI content change is documentation only. GetOrdersOpts, GetFillsOpts, and GetPositionsOpts gain ExchangeIndex, and GetHistoricalPositionsOpts gains Subaccount, matching the optional query parameters the spec already documents on those endpoints. Tests cover the parameter being sent and being omitted when nil. Fixes #8 Fixes #9 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… ListSubscriptions readLoop skipped a text frame that did not decode as JSON with no signal, leaving a corrupt stream looking healthy. It now records an error wrapping the new ErrWSMalformedFrame, closes the socket, and exits — the same path as ErrWSSlowConsumer. Frames received before the bad one are still delivered. Adds the missing success-path tests: Unsubscribe waits for one "unsubscribed" reply per sid, and ListSubscriptions decodes the "ok" reply whose msg is an array, both using the AsyncAPI example payloads. Fixes #10 Fixes #12 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to the 0.6.0 accuracy review. Patch release: every change is an addition or a bug fix, and
gorelease -base=v0.6.0reports only compatible changes.Fixes
APIError.Code/Messagewere empty for every production error.types.ErrorResponsefollows the spec's flat{"code","message","details"}, but production returns{"error":{"code":...,"message":...}}for most errors and{"msg":"..."}for parameter-binding 400s, soError()printed onlyapi error 404.newAPIErrornow decodes all three shapes (flat wins when both are present). Tests use the bodies observed from the live API.ErrWSMalformedFrame, closesMessages(), and returns that error from pending commands — same path asErrWSSlowConsumer. Frames received before the bad one are still delivered.Additions
Series.Categories(the full discovery list;Categoryis the primary and thecategoryfilter matches any entry) andGetTargetBalanceAllocationResponse.RestingMarginReservation.ExchangeIndexonGetOrdersOpts/GetFillsOpts/GetPositionsOpts,SubaccountonGetHistoricalPositionsOpts. Tests cover the parameter being sent and being omitted when nil.Unsubscribe(one reply per sid) andListSubscriptionssuccess paths, from the AsyncAPI example payloads.Docs
CreateV2example was missing the requiredself_trade_prevention_type; the not-implemented list omitted several paths; retry section states theRetry-Aftercap and the 409-on-replay behavior forclient_order_id; WebSocket section covers private channels, subscription-scopederrorframes (terminal codes 10/25), the AsyncAPI host, and server pings.cmd/example/README.mdno longer claimsLIVE=1forces production.AGENTS.md: tool-neutral contributor guide — layout, spec-sync workflow, conventions, the mandatory-test matrix, CI version-job rules, and the spec-vs-production differences above.Not in this PR
#11 (remove dead legacy V1 order types) is API-incompatible and needs a 0.7.0 with a
### Breakingsection; left open.Verification
gofmtclean ·go mod tidyno-op ·go vet·staticcheckclean ·go test -race -count=1 -shuffle=on ./...passes · version.go / CHANGELOG / README pin agree on 0.6.1 ·gorelease -base=v0.6.0 -version=v0.6.1: "v0.6.1 is a valid semantic version for this release" (only compatible additions).Fixes #7
Fixes #8
Fixes #9
Fixes #10
Fixes #12
🤖 Generated with Claude Code