Skip to content

Fix billing schema drift breaking credits/auth/models#7

Open
teox79 wants to merge 1 commit into
paperfoot:mainfrom
teox79:fix/billing-schema-drift
Open

Fix billing schema drift breaking credits/auth/models#7
teox79 wants to merge 1 commit into
paperfoot:mainfrom
teox79:fix/billing-schema-drift

Conversation

@teox79

@teox79 teox79 commented Jul 10, 2026

Copy link
Copy Markdown

Why

Suno's /api/billing/info/ endpoint has drifted from the schema this CLI expects. It no longer returns a nested plan: { name, plan_key } object or a period string — both were required fields on the Rust BillingInfo struct, so every command that touches billing (credits, auth, config check, models, etc.) failed to deserialize the response and errored out.

The live response now exposes subscription_type (either false for the free tier, or the active plan's plan_key string) plus a plans array describing the full catalog (id, key, name, pricing, features). Verified by making an authenticated live call against the real API and inspecting the current JSON shape.

What changed

  • src/api/types.rs: replaced the required plan/period/renews_on fields on BillingInfo with subscription_type: SubscriptionType (an untagged enum over bool/String) and plans: Vec<PlanOption>, matching the current API. Added a BillingInfo::plan_name() helper that resolves a human-readable plan name from subscription_type against the plans catalog (falls back to the raw key, or "Free").
  • src/main.rs: updated the two call sites that read info.plan.name to use the new plan_name() helper.
  • src/output/table.rs: updated the credits table renderer to use plan_name() and dropped the now-nonexistent Period/Renews On rows.

Testing

Built and ran the CLI locally against the live Suno API with a real authenticated session — suno credits, suno models, and suno config check all now succeed and render correctly (previously they failed with a deserialization error).

This is split out from a larger local commit so the critical fix can be reviewed/merged independently of the unrelated --title/v4.5-all additions (see companion PR).

Suno's /api/billing/info/ endpoint no longer returns a nested
`plan: { name, plan_key }` object or a `period` string — both were
required fields on the Rust BillingInfo struct, so every command
touching billing (credits, auth, config check, models) failed to
deserialize the response and errored out.

The live response now exposes `subscription_type` (either `false` for
the free tier, or the active plan's `plan_key` string) plus a `plans`
array describing the full catalog (id, key, name, pricing, features).
Verified against a live authenticated call to the current API.

Replace the required plan/period/renews_on fields with
subscription_type + plans, and add BillingInfo::plan_name() to resolve
a human-readable plan name from that catalog. Update the two call
sites that read info.plan.name and the credits table renderer
accordingly.
@teox79

teox79 commented Jul 10, 2026

Copy link
Copy Markdown
Author

Note: I noticed after opening this that #4 already addresses the same underlying billing-schema-drift issue, with a different (more defensive/generic) approach — making all BillingInfo/Plan/Model fields tolerant of absence via #[serde(default)], plus some unrelated auth.rs improvements (clearer Clerk error surfacing, session cleanup on --jwt).

One difference worth flagging: since the current API response has no plan key at all, #4's fallback synthesizes a placeholder plan name ("Active"/"Unknown") rather than resolving the real plan name. This PR instead models the current subscription_type + plans catalog shape directly, so it resolves the actual plan name (e.g. "Free Plan", "Pro Plan").

Happy to have you pick whichever approach you prefer, merge/adapt parts of both, or close this one if #4 already covers what you need — just flagging the overlap so it's not a surprise.

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.

1 participant