Fix billing schema drift breaking credits/auth/models#7
Conversation
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.
|
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 One difference worth flagging: since the current API response has no 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. |
Why
Suno's
/api/billing/info/endpoint has drifted from the schema this CLI expects. It no longer returns a nestedplan: { name, plan_key }object or aperiodstring — both were required fields on the RustBillingInfostruct, 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(eitherfalsefor the free tier, or the active plan'splan_keystring) plus aplansarray 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 requiredplan/period/renews_onfields onBillingInfowithsubscription_type: SubscriptionType(an untagged enum overbool/String) andplans: Vec<PlanOption>, matching the current API. Added aBillingInfo::plan_name()helper that resolves a human-readable plan name fromsubscription_typeagainst theplanscatalog (falls back to the raw key, or "Free").src/main.rs: updated the two call sites that readinfo.plan.nameto use the newplan_name()helper.src/output/table.rs: updated thecreditstable renderer to useplan_name()and dropped the now-nonexistentPeriod/Renews Onrows.Testing
Built and ran the CLI locally against the live Suno API with a real authenticated session —
suno credits,suno models, andsuno config checkall 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-alladditions (see companion PR).