[GH-ISSUE #74] Add In-App Purchases + Subscriptions management #20

Closed
opened 2026-02-26 21:32:49 +03:00 by kerem · 2 comments
Owner

Originally created by @rudrankriyam on GitHub (Jan 24, 2026).
Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/74

Summary

Add In-App Purchases + Subscriptions management. ASC currently has no IAP tooling.

Current State (verified)

Repo search for in-app purchases, subscriptions, price schedules returns no matches in commands/client.

API Endpoints (App Store Connect OpenAPI)

Core IAP (v2 recommended)

  • POST /v2/inAppPurchases
  • GET|PATCH|DELETE /v2/inAppPurchases/{id}
  • GET /v2/inAppPurchases/{id}/inAppPurchaseLocalizations
  • GET /v2/inAppPurchases/{id}/iapPriceSchedule
  • GET /v2/inAppPurchases/{id}/pricePoints
  • GET /v2/inAppPurchases/{id}/offerCodes
  • GET /v2/inAppPurchases/{id}/inAppPurchaseAvailability

Subscriptions

  • POST /v1/subscriptionGroups
  • GET|PATCH|DELETE /v1/subscriptionGroups/{id}
  • POST /v1/subscriptions
  • GET|PATCH|DELETE /v1/subscriptions/{id}
  • POST /v1/subscriptionPrices
  • DELETE /v1/subscriptionPrices/{id}
  • POST /v1/subscriptionAvailabilities
  • GET /v1/subscriptionAvailabilities/{id}

Offer codes / promos (optional phase 2)

  • POST /v1/subscriptionOfferCodes
  • POST /v1/subscriptionPromotionalOffers
  • POST /v1/inAppPurchaseOfferCodes

Proposed CLI (Phase 1)

asc iap create --app APP_ID --type CONSUMABLE|NON_CONSUMABLE|NON_RENEWING_SUBSCRIPTION|AUTO_RENEWABLE_SUBSCRIPTION --ref-name "Pro"
asc iap get --id IAP_ID
asc iap update --id IAP_ID --ref-name "New Name"
asc iap delete --id IAP_ID --confirm
asc iap localizations list --id IAP_ID

asc subscriptions groups list --app APP_ID
asc subscriptions groups create --app APP_ID --reference-name "Premium"
asc subscriptions create --group GROUP_ID --product-id com.example.sub
asc subscriptions get --id SUB_ID
asc subscriptions delete --id SUB_ID --confirm
asc subscriptions prices add --id SUB_ID --price-point PRICE_POINT_ID
asc subscriptions availability set --id SUB_ID --territory TERRITORY_ID[,TERRITORY_ID...]

Implementation Plan

  1. internal/asc/iap.go + internal/asc/subscriptions.go
  • Types for v2 IAP resources, localizations, price schedules.
  • Types for subscription groups, subscriptions, prices, availability.
  • Client methods for CRUD + list relationships.
  1. cmd/iap.go + cmd/subscriptions.go
  • New command groups with explicit flags and validations.
  1. Output helpers
  • Table/markdown for IAPs, subscription groups, subscriptions, pricing.
  1. Tests
  • CLI validation + HTTP client tests for CRUD and relationship endpoints.

Acceptance Criteria

  • Can create/list/get/update/delete IAPs and subscriptions.
  • Can manage subscription groups and add prices/availability.
  • JSON output by default; table/markdown supported.
Originally created by @rudrankriyam on GitHub (Jan 24, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/74 ## Summary Add In-App Purchases + Subscriptions management. ASC currently has no IAP tooling. ## Current State (verified) Repo search for in-app purchases, subscriptions, price schedules returns no matches in commands/client. ## API Endpoints (App Store Connect OpenAPI) Core IAP (v2 recommended) - `POST /v2/inAppPurchases` - `GET|PATCH|DELETE /v2/inAppPurchases/{id}` - `GET /v2/inAppPurchases/{id}/inAppPurchaseLocalizations` - `GET /v2/inAppPurchases/{id}/iapPriceSchedule` - `GET /v2/inAppPurchases/{id}/pricePoints` - `GET /v2/inAppPurchases/{id}/offerCodes` - `GET /v2/inAppPurchases/{id}/inAppPurchaseAvailability` Subscriptions - `POST /v1/subscriptionGroups` - `GET|PATCH|DELETE /v1/subscriptionGroups/{id}` - `POST /v1/subscriptions` - `GET|PATCH|DELETE /v1/subscriptions/{id}` - `POST /v1/subscriptionPrices` - `DELETE /v1/subscriptionPrices/{id}` - `POST /v1/subscriptionAvailabilities` - `GET /v1/subscriptionAvailabilities/{id}` Offer codes / promos (optional phase 2) - `POST /v1/subscriptionOfferCodes` - `POST /v1/subscriptionPromotionalOffers` - `POST /v1/inAppPurchaseOfferCodes` ## Proposed CLI (Phase 1) ``` asc iap create --app APP_ID --type CONSUMABLE|NON_CONSUMABLE|NON_RENEWING_SUBSCRIPTION|AUTO_RENEWABLE_SUBSCRIPTION --ref-name "Pro" asc iap get --id IAP_ID asc iap update --id IAP_ID --ref-name "New Name" asc iap delete --id IAP_ID --confirm asc iap localizations list --id IAP_ID asc subscriptions groups list --app APP_ID asc subscriptions groups create --app APP_ID --reference-name "Premium" asc subscriptions create --group GROUP_ID --product-id com.example.sub asc subscriptions get --id SUB_ID asc subscriptions delete --id SUB_ID --confirm asc subscriptions prices add --id SUB_ID --price-point PRICE_POINT_ID asc subscriptions availability set --id SUB_ID --territory TERRITORY_ID[,TERRITORY_ID...] ``` ## Implementation Plan 1) `internal/asc/iap.go` + `internal/asc/subscriptions.go` - Types for v2 IAP resources, localizations, price schedules. - Types for subscription groups, subscriptions, prices, availability. - Client methods for CRUD + list relationships. 2) `cmd/iap.go` + `cmd/subscriptions.go` - New command groups with explicit flags and validations. 3) Output helpers - Table/markdown for IAPs, subscription groups, subscriptions, pricing. 4) Tests - CLI validation + HTTP client tests for CRUD and relationship endpoints. ## Acceptance Criteria - Can create/list/get/update/delete IAPs and subscriptions. - Can manage subscription groups and add prices/availability. - JSON output by default; table/markdown supported.
kerem closed this issue 2026-02-26 21:32:49 +03:00
Author
Owner

@rudrankriyam commented on GitHub (Jan 24, 2026):

@cursor

Implementation Guide

Codebase Context

This is a large feature covering In-App Purchases (v2 API) and Subscriptions. Consider splitting into 2 PRs:

  1. Core IAP CRUD (consumable, non-consumable, non-renewing)
  2. Subscriptions (groups, subscriptions, pricing, availability)

File Structure

1. internal/asc/iap.go (~250-300 lines)

// InAppPurchase types (v2 API)
type InAppPurchaseV2Attributes struct {
    Name               string `json:"name"`
    ProductID          string `json:"productId"`
    InAppPurchaseType  string `json:"inAppPurchaseType"` // CONSUMABLE, NON_CONSUMABLE, NON_RENEWING_SUBSCRIPTION
    State              string `json:"state,omitempty"`   // MISSING_METADATA, READY_TO_SUBMIT, WAITING_FOR_REVIEW, etc.
    ReviewNote         string `json:"reviewNote,omitempty"`
    FamilySharable     bool   `json:"familySharable,omitempty"`
    ContentHosting     bool   `json:"contentHosting,omitempty"`
    AvailableInAllTerritories bool `json:"availableInAllTerritories,omitempty"`
}

type InAppPurchaseLocalizationAttributes struct {
    Name        string `json:"name"`
    Locale      string `json:"locale"`
    Description string `json:"description,omitempty"`
}

type InAppPurchasePriceScheduleAttributes struct {
    // Price schedule relationships
}

// Response types
type InAppPurchasesV2Response = Response[InAppPurchaseV2Attributes]
type InAppPurchaseV2Response = SingleResponse[InAppPurchaseV2Attributes]
type InAppPurchaseLocalizationsResponse = Response[InAppPurchaseLocalizationAttributes]

// IAP types enum
var ValidIAPTypes = []string{
    "CONSUMABLE",
    "NON_CONSUMABLE", 
    "NON_RENEWING_SUBSCRIPTION",
}

2. internal/asc/subscriptions.go (~300-350 lines)

// Subscription Group types
type SubscriptionGroupAttributes struct {
    ReferenceName string `json:"referenceName"`
}

// Subscription types
type SubscriptionAttributes struct {
    Name                 string `json:"name"`
    ProductID            string `json:"productId"`
    FamilySharable       bool   `json:"familySharable,omitempty"`
    State                string `json:"state,omitempty"`
    SubscriptionPeriod   string `json:"subscriptionPeriod,omitempty"` // ONE_WEEK, ONE_MONTH, etc.
    ReviewNote           string `json:"reviewNote,omitempty"`
    GroupLevel           int    `json:"groupLevel,omitempty"`
    AvailableInAllTerritories bool `json:"availableInAllTerritories,omitempty"`
}

type SubscriptionPriceAttributes struct {
    StartDate   string `json:"startDate,omitempty"`
    Preserved   bool   `json:"preserved,omitempty"`
}

type SubscriptionAvailabilityAttributes struct {
    AvailableInNewTerritories bool `json:"availableInNewTerritories"`
}

// Response types
type SubscriptionGroupsResponse = Response[SubscriptionGroupAttributes]
type SubscriptionGroupResponse = SingleResponse[SubscriptionGroupAttributes]
type SubscriptionsResponse = Response[SubscriptionAttributes]
type SubscriptionResponse = SingleResponse[SubscriptionAttributes]
type SubscriptionPricesResponse = Response[SubscriptionPriceAttributes]
type SubscriptionAvailabilityResponse = SingleResponse[SubscriptionAvailabilityAttributes]

3. internal/asc/client_iap.go (~150-200 lines)

// In-App Purchases (v2)
func (c *Client) GetInAppPurchasesV2(ctx context.Context, appID string, opts ...IAPOption) (*InAppPurchasesV2Response, error)
func (c *Client) GetInAppPurchaseV2(ctx context.Context, iapID string) (*InAppPurchaseV2Response, error)
func (c *Client) CreateInAppPurchaseV2(ctx context.Context, appID string, attrs InAppPurchaseV2CreateAttributes) (*InAppPurchaseV2Response, error)
func (c *Client) UpdateInAppPurchaseV2(ctx context.Context, iapID string, attrs InAppPurchaseV2UpdateAttributes) (*InAppPurchaseV2Response, error)
func (c *Client) DeleteInAppPurchaseV2(ctx context.Context, iapID string) error
func (c *Client) GetInAppPurchaseLocalizations(ctx context.Context, iapID string) (*InAppPurchaseLocalizationsResponse, error)

4. internal/asc/client_subscriptions.go (~200-250 lines)

// Subscription Groups
func (c *Client) GetSubscriptionGroups(ctx context.Context, appID string, opts ...SubscriptionGroupsOption) (*SubscriptionGroupsResponse, error)
func (c *Client) CreateSubscriptionGroup(ctx context.Context, appID string, attrs SubscriptionGroupCreateAttributes) (*SubscriptionGroupResponse, error)
func (c *Client) GetSubscriptionGroup(ctx context.Context, groupID string) (*SubscriptionGroupResponse, error)
func (c *Client) UpdateSubscriptionGroup(ctx context.Context, groupID string, attrs SubscriptionGroupUpdateAttributes) (*SubscriptionGroupResponse, error)
func (c *Client) DeleteSubscriptionGroup(ctx context.Context, groupID string) error

// Subscriptions
func (c *Client) GetSubscriptions(ctx context.Context, groupID string, opts ...SubscriptionsOption) (*SubscriptionsResponse, error)
func (c *Client) CreateSubscription(ctx context.Context, groupID string, attrs SubscriptionCreateAttributes) (*SubscriptionResponse, error)
func (c *Client) GetSubscription(ctx context.Context, subID string) (*SubscriptionResponse, error)
func (c *Client) UpdateSubscription(ctx context.Context, subID string, attrs SubscriptionUpdateAttributes) (*SubscriptionResponse, error)
func (c *Client) DeleteSubscription(ctx context.Context, subID string) error

// Subscription Pricing & Availability
func (c *Client) CreateSubscriptionPrice(ctx context.Context, subID string, attrs SubscriptionPriceCreateAttributes) (*SubscriptionPriceResponse, error)
func (c *Client) DeleteSubscriptionPrice(ctx context.Context, priceID string) error
func (c *Client) GetSubscriptionAvailability(ctx context.Context, subID string) (*SubscriptionAvailabilityResponse, error)
func (c *Client) CreateSubscriptionAvailability(ctx context.Context, subID string, attrs SubscriptionAvailabilityCreateAttributes) (*SubscriptionAvailabilityResponse, error)

5. internal/asc/iap_output.go + internal/asc/subscriptions_output.go** (~100 lines each)

6. cmd/iap.go (~300 lines)

func IAPCommand() *ffcli.Command  // Parent

func IAPListCommand() *ffcli.Command      // --app APP_ID
func IAPGetCommand() *ffcli.Command       // --id IAP_ID  
func IAPCreateCommand() *ffcli.Command    // --app --type --ref-name --product-id
func IAPUpdateCommand() *ffcli.Command    // --id --ref-name
func IAPDeleteCommand() *ffcli.Command    // --id --confirm
func IAPLocalizationsCommand() *ffcli.Command  // --id (list localizations)

7. cmd/subscriptions.go (~350-400 lines)

func SubscriptionsCommand() *ffcli.Command  // Parent

// Groups
func SubscriptionsGroupsCommand() *ffcli.Command     // Nested group
func SubscriptionsGroupsListCommand() *ffcli.Command
func SubscriptionsGroupsCreateCommand() *ffcli.Command
func SubscriptionsGroupsGetCommand() *ffcli.Command
func SubscriptionsGroupsDeleteCommand() *ffcli.Command

// Subscriptions
func SubscriptionsListCommand() *ffcli.Command
func SubscriptionsCreateCommand() *ffcli.Command
func SubscriptionsGetCommand() *ffcli.Command
func SubscriptionsDeleteCommand() *ffcli.Command

// Pricing
func SubscriptionsPricesCommand() *ffcli.Command
func SubscriptionsAvailabilityCommand() *ffcli.Command

8. Register in cmd/commands.go
Add IAPCommand() and SubscriptionsCommand() to RootCommand().Subcommands

API Endpoints Reference

In-App Purchases (v2):
GET    /v2/inAppPurchases                                → via app relationship
POST   /v2/inAppPurchases                                → CreateInAppPurchaseV2
GET    /v2/inAppPurchases/{id}                           → GetInAppPurchaseV2
PATCH  /v2/inAppPurchases/{id}                           → UpdateInAppPurchaseV2
DELETE /v2/inAppPurchases/{id}                           → DeleteInAppPurchaseV2
GET    /v2/inAppPurchases/{id}/inAppPurchaseLocalizations → GetInAppPurchaseLocalizations

Subscription Groups:
GET    /v1/apps/{id}/subscriptionGroups                  → GetSubscriptionGroups
POST   /v1/subscriptionGroups                            → CreateSubscriptionGroup
GET    /v1/subscriptionGroups/{id}                       → GetSubscriptionGroup
PATCH  /v1/subscriptionGroups/{id}                       → UpdateSubscriptionGroup
DELETE /v1/subscriptionGroups/{id}                       → DeleteSubscriptionGroup

Subscriptions:
GET    /v1/subscriptionGroups/{id}/subscriptions         → GetSubscriptions
POST   /v1/subscriptions                                 → CreateSubscription
GET    /v1/subscriptions/{id}                            → GetSubscription
PATCH  /v1/subscriptions/{id}                            → UpdateSubscription
DELETE /v1/subscriptions/{id}                            → DeleteSubscription

Pricing/Availability:
POST   /v1/subscriptionPrices                            → CreateSubscriptionPrice
DELETE /v1/subscriptionPrices/{id}                       → DeleteSubscriptionPrice
POST   /v1/subscriptionAvailabilities                    → CreateSubscriptionAvailability
GET    /v1/subscriptionAvailabilities/{id}               → GetSubscriptionAvailability

Testing

  • Run make test && make lint
  • Test IAP type validation
  • Test subscription creation with required relationships
<!-- gh-comment-id:3795328753 --> @rudrankriyam commented on GitHub (Jan 24, 2026): @cursor ## Implementation Guide ### Codebase Context This is a large feature covering In-App Purchases (v2 API) and Subscriptions. Consider splitting into 2 PRs: 1. Core IAP CRUD (consumable, non-consumable, non-renewing) 2. Subscriptions (groups, subscriptions, pricing, availability) ### File Structure **1. `internal/asc/iap.go`** (~250-300 lines) ```go // InAppPurchase types (v2 API) type InAppPurchaseV2Attributes struct { Name string `json:"name"` ProductID string `json:"productId"` InAppPurchaseType string `json:"inAppPurchaseType"` // CONSUMABLE, NON_CONSUMABLE, NON_RENEWING_SUBSCRIPTION State string `json:"state,omitempty"` // MISSING_METADATA, READY_TO_SUBMIT, WAITING_FOR_REVIEW, etc. ReviewNote string `json:"reviewNote,omitempty"` FamilySharable bool `json:"familySharable,omitempty"` ContentHosting bool `json:"contentHosting,omitempty"` AvailableInAllTerritories bool `json:"availableInAllTerritories,omitempty"` } type InAppPurchaseLocalizationAttributes struct { Name string `json:"name"` Locale string `json:"locale"` Description string `json:"description,omitempty"` } type InAppPurchasePriceScheduleAttributes struct { // Price schedule relationships } // Response types type InAppPurchasesV2Response = Response[InAppPurchaseV2Attributes] type InAppPurchaseV2Response = SingleResponse[InAppPurchaseV2Attributes] type InAppPurchaseLocalizationsResponse = Response[InAppPurchaseLocalizationAttributes] // IAP types enum var ValidIAPTypes = []string{ "CONSUMABLE", "NON_CONSUMABLE", "NON_RENEWING_SUBSCRIPTION", } ``` **2. `internal/asc/subscriptions.go`** (~300-350 lines) ```go // Subscription Group types type SubscriptionGroupAttributes struct { ReferenceName string `json:"referenceName"` } // Subscription types type SubscriptionAttributes struct { Name string `json:"name"` ProductID string `json:"productId"` FamilySharable bool `json:"familySharable,omitempty"` State string `json:"state,omitempty"` SubscriptionPeriod string `json:"subscriptionPeriod,omitempty"` // ONE_WEEK, ONE_MONTH, etc. ReviewNote string `json:"reviewNote,omitempty"` GroupLevel int `json:"groupLevel,omitempty"` AvailableInAllTerritories bool `json:"availableInAllTerritories,omitempty"` } type SubscriptionPriceAttributes struct { StartDate string `json:"startDate,omitempty"` Preserved bool `json:"preserved,omitempty"` } type SubscriptionAvailabilityAttributes struct { AvailableInNewTerritories bool `json:"availableInNewTerritories"` } // Response types type SubscriptionGroupsResponse = Response[SubscriptionGroupAttributes] type SubscriptionGroupResponse = SingleResponse[SubscriptionGroupAttributes] type SubscriptionsResponse = Response[SubscriptionAttributes] type SubscriptionResponse = SingleResponse[SubscriptionAttributes] type SubscriptionPricesResponse = Response[SubscriptionPriceAttributes] type SubscriptionAvailabilityResponse = SingleResponse[SubscriptionAvailabilityAttributes] ``` **3. `internal/asc/client_iap.go`** (~150-200 lines) ```go // In-App Purchases (v2) func (c *Client) GetInAppPurchasesV2(ctx context.Context, appID string, opts ...IAPOption) (*InAppPurchasesV2Response, error) func (c *Client) GetInAppPurchaseV2(ctx context.Context, iapID string) (*InAppPurchaseV2Response, error) func (c *Client) CreateInAppPurchaseV2(ctx context.Context, appID string, attrs InAppPurchaseV2CreateAttributes) (*InAppPurchaseV2Response, error) func (c *Client) UpdateInAppPurchaseV2(ctx context.Context, iapID string, attrs InAppPurchaseV2UpdateAttributes) (*InAppPurchaseV2Response, error) func (c *Client) DeleteInAppPurchaseV2(ctx context.Context, iapID string) error func (c *Client) GetInAppPurchaseLocalizations(ctx context.Context, iapID string) (*InAppPurchaseLocalizationsResponse, error) ``` **4. `internal/asc/client_subscriptions.go`** (~200-250 lines) ```go // Subscription Groups func (c *Client) GetSubscriptionGroups(ctx context.Context, appID string, opts ...SubscriptionGroupsOption) (*SubscriptionGroupsResponse, error) func (c *Client) CreateSubscriptionGroup(ctx context.Context, appID string, attrs SubscriptionGroupCreateAttributes) (*SubscriptionGroupResponse, error) func (c *Client) GetSubscriptionGroup(ctx context.Context, groupID string) (*SubscriptionGroupResponse, error) func (c *Client) UpdateSubscriptionGroup(ctx context.Context, groupID string, attrs SubscriptionGroupUpdateAttributes) (*SubscriptionGroupResponse, error) func (c *Client) DeleteSubscriptionGroup(ctx context.Context, groupID string) error // Subscriptions func (c *Client) GetSubscriptions(ctx context.Context, groupID string, opts ...SubscriptionsOption) (*SubscriptionsResponse, error) func (c *Client) CreateSubscription(ctx context.Context, groupID string, attrs SubscriptionCreateAttributes) (*SubscriptionResponse, error) func (c *Client) GetSubscription(ctx context.Context, subID string) (*SubscriptionResponse, error) func (c *Client) UpdateSubscription(ctx context.Context, subID string, attrs SubscriptionUpdateAttributes) (*SubscriptionResponse, error) func (c *Client) DeleteSubscription(ctx context.Context, subID string) error // Subscription Pricing & Availability func (c *Client) CreateSubscriptionPrice(ctx context.Context, subID string, attrs SubscriptionPriceCreateAttributes) (*SubscriptionPriceResponse, error) func (c *Client) DeleteSubscriptionPrice(ctx context.Context, priceID string) error func (c *Client) GetSubscriptionAvailability(ctx context.Context, subID string) (*SubscriptionAvailabilityResponse, error) func (c *Client) CreateSubscriptionAvailability(ctx context.Context, subID string, attrs SubscriptionAvailabilityCreateAttributes) (*SubscriptionAvailabilityResponse, error) ``` **5. `internal/asc/iap_output.go`** + `internal/asc/subscriptions_output.go`** (~100 lines each) **6. `cmd/iap.go`** (~300 lines) ```go func IAPCommand() *ffcli.Command // Parent func IAPListCommand() *ffcli.Command // --app APP_ID func IAPGetCommand() *ffcli.Command // --id IAP_ID func IAPCreateCommand() *ffcli.Command // --app --type --ref-name --product-id func IAPUpdateCommand() *ffcli.Command // --id --ref-name func IAPDeleteCommand() *ffcli.Command // --id --confirm func IAPLocalizationsCommand() *ffcli.Command // --id (list localizations) ``` **7. `cmd/subscriptions.go`** (~350-400 lines) ```go func SubscriptionsCommand() *ffcli.Command // Parent // Groups func SubscriptionsGroupsCommand() *ffcli.Command // Nested group func SubscriptionsGroupsListCommand() *ffcli.Command func SubscriptionsGroupsCreateCommand() *ffcli.Command func SubscriptionsGroupsGetCommand() *ffcli.Command func SubscriptionsGroupsDeleteCommand() *ffcli.Command // Subscriptions func SubscriptionsListCommand() *ffcli.Command func SubscriptionsCreateCommand() *ffcli.Command func SubscriptionsGetCommand() *ffcli.Command func SubscriptionsDeleteCommand() *ffcli.Command // Pricing func SubscriptionsPricesCommand() *ffcli.Command func SubscriptionsAvailabilityCommand() *ffcli.Command ``` **8. Register in `cmd/commands.go`** Add `IAPCommand()` and `SubscriptionsCommand()` to RootCommand().Subcommands ### API Endpoints Reference ``` In-App Purchases (v2): GET /v2/inAppPurchases → via app relationship POST /v2/inAppPurchases → CreateInAppPurchaseV2 GET /v2/inAppPurchases/{id} → GetInAppPurchaseV2 PATCH /v2/inAppPurchases/{id} → UpdateInAppPurchaseV2 DELETE /v2/inAppPurchases/{id} → DeleteInAppPurchaseV2 GET /v2/inAppPurchases/{id}/inAppPurchaseLocalizations → GetInAppPurchaseLocalizations Subscription Groups: GET /v1/apps/{id}/subscriptionGroups → GetSubscriptionGroups POST /v1/subscriptionGroups → CreateSubscriptionGroup GET /v1/subscriptionGroups/{id} → GetSubscriptionGroup PATCH /v1/subscriptionGroups/{id} → UpdateSubscriptionGroup DELETE /v1/subscriptionGroups/{id} → DeleteSubscriptionGroup Subscriptions: GET /v1/subscriptionGroups/{id}/subscriptions → GetSubscriptions POST /v1/subscriptions → CreateSubscription GET /v1/subscriptions/{id} → GetSubscription PATCH /v1/subscriptions/{id} → UpdateSubscription DELETE /v1/subscriptions/{id} → DeleteSubscription Pricing/Availability: POST /v1/subscriptionPrices → CreateSubscriptionPrice DELETE /v1/subscriptionPrices/{id} → DeleteSubscriptionPrice POST /v1/subscriptionAvailabilities → CreateSubscriptionAvailability GET /v1/subscriptionAvailabilities/{id} → GetSubscriptionAvailability ``` ### Testing - Run `make test && make lint` - Test IAP type validation - Test subscription creation with required relationships
Author
Owner

@cursor[bot] commented on GitHub (Jan 24, 2026):

Thanks for the detailed implementation guide — this lines up well with the plan.

I’ll follow the suggested split into two PRs:

  1. Core IAP CRUD (v2): types + client + output + CLI + tests
  2. Subscriptions: groups/subscriptions/pricing/availability

For PR #1 I’ll add internal/asc/iap.go, internal/asc/client_iap.go, internal/asc/iap_output.go, and cmd/iap.go, then register IAPCommand() in cmd/commands.go. I’ll keep the type definitions and method signatures aligned with your snippets and the v2 endpoints. I’ll also add CLI validation for ValidIAPTypes, and client tests for create/get/update/delete/localizations.

For PR #2 I’ll mirror the structure with internal/asc/subscriptions.go, internal/asc/client_subscriptions.go, internal/asc/subscriptions_output.go, cmd/subscriptions.go, and register SubscriptionsCommand().

Testing plan: make test && make lint, plus targeted unit tests for IAP type validation and subscription required relationships.

If you want any extra endpoints included in phase 1 (e.g., price points, availability), let me know; otherwise I’ll keep those for phase 2.

Create PR
Open in Cursor Open in Web

<!-- gh-comment-id:3795328807 --> @cursor[bot] commented on GitHub (Jan 24, 2026): Thanks for the detailed implementation guide — this lines up well with the plan. I’ll follow the suggested split into two PRs: 1) **Core IAP CRUD (v2)**: types + client + output + CLI + tests 2) **Subscriptions**: groups/subscriptions/pricing/availability For PR #1 I’ll add `internal/asc/iap.go`, `internal/asc/client_iap.go`, `internal/asc/iap_output.go`, and `cmd/iap.go`, then register `IAPCommand()` in `cmd/commands.go`. I’ll keep the type definitions and method signatures aligned with your snippets and the v2 endpoints. I’ll also add CLI validation for `ValidIAPTypes`, and client tests for create/get/update/delete/localizations. For PR #2 I’ll mirror the structure with `internal/asc/subscriptions.go`, `internal/asc/client_subscriptions.go`, `internal/asc/subscriptions_output.go`, `cmd/subscriptions.go`, and register `SubscriptionsCommand()`. Testing plan: `make test && make lint`, plus targeted unit tests for IAP type validation and subscription required relationships. If you want any extra endpoints included in phase 1 (e.g., price points, availability), let me know; otherwise I’ll keep those for phase 2. <a href="https://github.com/rudrankriyam/App-Store-Connect-CLI/compare/main...cursor/in-app-purchases-and-subscriptions-5fad?expand=1&title=In-app%20purchases%20and%20subscriptions&body=Implement%20core%20CRUD%20for%20In-App%20Purchases%20(v2%20API)%20as%20the%20first%20phase%20of%20the%20IAP%20and%20Subscriptions%20feature.%0A%0A---%0A%3Ca%20href%3D%22https%3A%2F%2Fcursor.com%2Fbackground-agent%3FbcId%3Dbc-33ebdf62-b9b8-416a-a9e3-21ef451900b9%22%3E%3Cpicture%3E%3Csource%20media%3D%22(prefers-color-scheme%3A%20dark)%22%20srcset%3D%22https%3A%2F%2Fcursor.com%2Fopen-in-cursor-dark.svg%22%3E%3Csource%20media%3D%22(prefers-color-scheme%3A%20light)%22%20srcset%3D%22https%3A%2F%2Fcursor.com%2Fopen-in-cursor-light.svg%22%3E%3Cimg%20alt%3D%22Open%20in%20Cursor%22%20src%3D%22https%3A%2F%2Fcursor.com%2Fopen-in-cursor.svg%22%3E%3C%2Fpicture%3E%3C%2Fa%3E%26nbsp%3B%3Ca%20href%3D%22https%3A%2F%2Fcursor.com%2Fagents%3Fid%3Dbc-33ebdf62-b9b8-416a-a9e3-21ef451900b9%22%3E%3Cpicture%3E%3Csource%20media%3D%22(prefers-color-scheme%3A%20dark)%22%20srcset%3D%22https%3A%2F%2Fcursor.com%2Fopen-in-web-dark.svg%22%3E%3Csource%20media%3D%22(prefers-color-scheme%3A%20light)%22%20srcset%3D%22https%3A%2F%2Fcursor.com%2Fopen-in-web-light.svg%22%3E%3Cimg%20alt%3D%22Open%20in%20Web%22%20src%3D%22https%3A%2F%2Fcursor.com%2Fopen-in-web.svg%22%3E%3C%2Fpicture%3E%3C%2Fa%3E"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/create-pr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/create-pr-light.svg"><img alt="Create PR" src="https://cursor.com/create-pr-light.svg"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-33ebdf62-b9b8-416a-a9e3-21ef451900b9"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-cursor-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-cursor-light.svg"><img alt="Open in Cursor" src="https://cursor.com/open-in-cursor.svg"></picture></a>&nbsp;<a href="https://cursor.com/agents?id=bc-33ebdf62-b9b8-416a-a9e3-21ef451900b9"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/open-in-web-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/open-in-web-light.svg"><img alt="Open in Web" src="https://cursor.com/open-in-web.svg"></picture></a>
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#20
No description provided.