[GH-ISSUE #398] Please expose subscription period + grace period #112

Closed
opened 2026-02-26 21:33:30 +03:00 by kerem · 4 comments
Owner

Originally created by @flutterrausch on GitHub (Feb 2, 2026).
Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/398

Sorry for not making a PR myself - never did one, no time RN. Hope this is good enough :)

The **API supports subscription period **, but the CLI doesn't expose it as a flag.

What the App Store Connect API actually supports

Looking at the internal structs in asc:

// SubscriptionCreateAttributes describes attributes for creating a subscription.
type SubscriptionCreateAttributes struct {
    Name                      string  `json:"name"`
    ProductID                 string  `json:"productId"`
    FamilySharable            *bool   `json:"familySharable,omitempty"`
    SubscriptionPeriod        string  `json:"subscriptionPeriod,omitempty"`  // <-- EXISTS
    ReviewNote                string  `json:"reviewNote,omitempty"`
    GroupLevel                *int    `json:"groupLevel,omitempty"`
    AvailableInAllTerritories *bool   `json:"availableInAllTerritories,omitempty"`
}

The SubscriptionPeriod field is there for create and update. Valid values (per Apple's API docs) are:

  • ONE_WEEK
  • ONE_MONTH
  • TWO_MONTHS
  • THREE_MONTHS
  • SIX_MONTHS
  • ONE_YEAR

Why the CLI doesn't expose it

The CLI command (asc subscriptions create) only wires up these flags:

--group        Subscription group ID
--product-id   Product ID (e.g., com.example.sub)
--ref-name     Reference name

The Go code passes Name and ProductID to the API, but never sets SubscriptionPeriod even though the struct supports it. This is simply an incomplete CLI implementation.

What you CAN set up with asc today

Feature asc support
Subscription groups create, list, get, update, delete
Subscriptions create (no period), list, get, update (no period), delete
Subscription period not exposed (API supports it)
Prices per territory add, list, delete
Price points & equalizations list, query
Localizations (name/description) create, update, delete
Introductory offers (trials) create, update, delete
Review screenshots upload, update, delete
Promotional offers create, update, delete
Availability set territories
Grace period read-only

Options to fix this

expose --subscription-period on subscriptions create and subscriptions update. It's a small change (add the flag and wire it to the struct).

Grace period

Same thing I think, fixed to 14d would be alright.

Originally created by @flutterrausch on GitHub (Feb 2, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/398 Sorry for not making a PR myself - never did one, no time RN. Hope this is good enough :) The **API supports subscription period **, but the **CLI doesn't expose it as a flag**. ## What the App Store Connect API actually supports Looking at the internal structs in `asc`: ```go // SubscriptionCreateAttributes describes attributes for creating a subscription. type SubscriptionCreateAttributes struct { Name string `json:"name"` ProductID string `json:"productId"` FamilySharable *bool `json:"familySharable,omitempty"` SubscriptionPeriod string `json:"subscriptionPeriod,omitempty"` // <-- EXISTS ReviewNote string `json:"reviewNote,omitempty"` GroupLevel *int `json:"groupLevel,omitempty"` AvailableInAllTerritories *bool `json:"availableInAllTerritories,omitempty"` } ``` The `SubscriptionPeriod` field is there for create and update. Valid values (per Apple's API docs) are: - `ONE_WEEK` - `ONE_MONTH` - `TWO_MONTHS` - `THREE_MONTHS` - `SIX_MONTHS` - `ONE_YEAR` ## Why the CLI doesn't expose it The CLI command (`asc subscriptions create`) only wires up these flags: ``` --group Subscription group ID --product-id Product ID (e.g., com.example.sub) --ref-name Reference name ``` The Go code passes `Name` and `ProductID` to the API, but **never sets `SubscriptionPeriod`** even though the struct supports it. This is simply an incomplete CLI implementation. ## What you CAN set up with asc today | Feature | asc support | |---------|-------------| | Subscription groups | create, list, get, update, delete | | Subscriptions | create (no period), list, get, update (no period), delete | | Subscription period | **not exposed** (API supports it) | | Prices per territory | add, list, delete | | Price points & equalizations | list, query | | Localizations (name/description) | create, update, delete | | Introductory offers (trials) | create, update, delete | | Review screenshots | upload, update, delete | | Promotional offers | create, update, delete | | Availability | set territories | | Grace period | **read-only** | ## Options to fix this expose `--subscription-period` on `subscriptions create` and `subscriptions update`. It's a small change (add the flag and wire it to the struct). ## Grace period Same thing I think, fixed to 14d would be alright.
kerem closed this issue 2026-02-26 21:33:30 +03:00
Author
Owner

@rudrankriyam commented on GitHub (Feb 2, 2026):

@cursor please implement this. Go through the openapi spec and add it

<!-- gh-comment-id:3834611380 --> @rudrankriyam commented on GitHub (Feb 2, 2026): @cursor please implement this. Go through the openapi spec and add it
Author
Owner

@cursor[bot] commented on GitHub (Feb 2, 2026):

Summary:

  • I wired --subscription-period into subscriptions create and subscriptions update with validation so the API request includes the chosen period (ONE_WEEK, ONE_MONTH, TWO_MONTHS, THREE_MONTHS, SIX_MONTHS, ONE_YEAR).
// ...
subscriptionPeriod := fs.String("subscription-period", "", "Subscription period: "+strings.Join(subscriptionPeriodValues, ", "))
// ...
period, err := normalizeSubscriptionPeriod(*subscriptionPeriod, false)
// ...
if period != "" {
	attrs.SubscriptionPeriod = string(period)
}
// ...
subscriptionPeriod := fs.String("subscription-period", "", "Subscription period: "+strings.Join(subscriptionPeriodValues, ", "))
// ...
period, err := normalizeSubscriptionPeriod(*subscriptionPeriod, false)
// ...
if period != "" {
	periodValue := string(period)
	attrs.SubscriptionPeriod = &periodValue
}
  • I added subscriptions grace-periods update with opt-in/sandbox opt-in, duration, and renewal-type flags, and wired it to the update call.
func SubscriptionsGracePeriodsUpdateCommand() *ffcli.Command {
	// ...
	duration := fs.String("duration", "", "Grace period duration: "+strings.Join(subscriptionGracePeriodDurationValues, ", "))
	renewalType := fs.String("renewal-type", "", "Grace period renewal type: "+strings.Join(subscriptionGracePeriodRenewalTypeValues, ", "))
	// ...
	attrs := asc.SubscriptionGracePeriodUpdateAttributes{}
	// ...
	resp, err := client.UpdateSubscriptionGracePeriod(requestCtx, id, attrs)
	// ...
}

Testing:

  • make test

Walkthrough artifact:

  • cli_subscription_period_grace_period_help_visible/recording_demo.mp4 (shows go run . subscriptions create --help and go run . subscriptions grace-periods update --help with the new flags).

View PR
Open in Cursor Open in Web

<!-- gh-comment-id:3834611819 --> @cursor[bot] commented on GitHub (Feb 2, 2026): Summary: - I wired `--subscription-period` into `subscriptions create` and `subscriptions update` with validation so the API request includes the chosen period (ONE_WEEK, ONE_MONTH, TWO_MONTHS, THREE_MONTHS, SIX_MONTHS, ONE_YEAR). ```448:509:internal/cli/subscriptions/subscriptions.go // ... subscriptionPeriod := fs.String("subscription-period", "", "Subscription period: "+strings.Join(subscriptionPeriodValues, ", ")) // ... period, err := normalizeSubscriptionPeriod(*subscriptionPeriod, false) // ... if period != "" { attrs.SubscriptionPeriod = string(period) } ``` ```564:618:internal/cli/subscriptions/subscriptions.go // ... subscriptionPeriod := fs.String("subscription-period", "", "Subscription period: "+strings.Join(subscriptionPeriodValues, ", ")) // ... period, err := normalizeSubscriptionPeriod(*subscriptionPeriod, false) // ... if period != "" { periodValue := string(period) attrs.SubscriptionPeriod = &periodValue } ``` - I added `subscriptions grace-periods update` with opt-in/sandbox opt-in, duration, and renewal-type flags, and wired it to the update call. ```84:162:internal/cli/subscriptions/grace_periods.go func SubscriptionsGracePeriodsUpdateCommand() *ffcli.Command { // ... duration := fs.String("duration", "", "Grace period duration: "+strings.Join(subscriptionGracePeriodDurationValues, ", ")) renewalType := fs.String("renewal-type", "", "Grace period renewal type: "+strings.Join(subscriptionGracePeriodRenewalTypeValues, ", ")) // ... attrs := asc.SubscriptionGracePeriodUpdateAttributes{} // ... resp, err := client.UpdateSubscriptionGracePeriod(requestCtx, id, attrs) // ... } ``` Testing: - `make test` Walkthrough artifact: - `cli_subscription_period_grace_period_help_visible/recording_demo.mp4` (shows `go run . subscriptions create --help` and `go run . subscriptions grace-periods update --help` with the new flags). <a href="https://github.com/rudrankriyam/App-Store-Connect-CLI/pull/399"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/view-pr-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/view-pr-light.png"><img alt="View PR" width="86" height="28" src="https://cursor.com/assets/images/view-pr-light.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-a4a135fd-3571-49ca-bc7f-800e6300add5"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/agents?id=bc-a4a135fd-3571-49ca-bc7f-800e6300add5"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>
Author
Owner

@rudrankriyam commented on GitHub (Feb 2, 2026):

Thanks for the report! This is now fixed in v0.23.5 (tagged release).

Changes included:

  • Added --subscription-period to asc subscriptions create and asc subscriptions update.
  • Added asc subscriptions grace-periods update for opt-in, sandbox opt-in, duration, and renewal type.

Note: the App Store Connect API currently rejects updates to subscriptionPeriod on existing subscriptions ("SubscriptionPeriod cannot be updated.") — create supports it, update does not.

Release: https://github.com/rudrankriyam/App-Store-Connect-CLI/releases/tag/0.23.5

<!-- gh-comment-id:3834906448 --> @rudrankriyam commented on GitHub (Feb 2, 2026): Thanks for the report! This is now fixed in v0.23.5 (tagged release). Changes included: - Added `--subscription-period` to `asc subscriptions create` and `asc subscriptions update`. - Added `asc subscriptions grace-periods update` for opt-in, sandbox opt-in, duration, and renewal type. Note: the App Store Connect API currently rejects updates to `subscriptionPeriod` on existing subscriptions ("SubscriptionPeriod cannot be updated.") — create supports it, update does not. Release: https://github.com/rudrankriyam/App-Store-Connect-CLI/releases/tag/0.23.5
Author
Owner

@flutterrausch commented on GitHub (Feb 2, 2026):

Wow, you are the speed king, thanks a lot!

❤️

<!-- gh-comment-id:3835090186 --> @flutterrausch commented on GitHub (Feb 2, 2026): Wow, you are the speed king, thanks a lot! ❤️
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/App-Store-Connect-CLI#112
No description provided.