Documentation
¶
Overview ¶
Package catalog provides a Go client for Apple's Apps and Books for Organizations API.
The catalog API is separate from Apple's VPP management API and is intended for storefront-aware metadata retrieval. This package includes:
- typed app, book, search, and storefront queries
- owned app and owned book metadata lookups for sToken-authenticated calls
- ES256 developer-token generation helpers
- forward-compatible response models that preserve unknown JSON fields
The main entry point is NewClient. Runnable usage snippets are available in example_test.go.
Index ¶
- Variables
- func GenerateDeveloperToken(keyID, teamID string, privateKeyPEM []byte, opts GenerateDeveloperTokenOptions) (string, error)
- type APIError
- type AllStorefrontsQuery
- type App
- type AppAttributes
- type AppPlatformAttributes
- type AppsResponse
- type Artwork
- type Book
- type BookAttributes
- type BooksResponse
- type CatalogAppQuery
- type CatalogAppsQuery
- type CatalogBookQuery
- type CatalogBooksQuery
- type Client
- func (c *Client) GetAllStorefronts(ctx context.Context, query AllStorefrontsQuery) (*StorefrontsResponse, error)
- func (c *Client) GetApp(ctx context.Context, storefront, id string, query CatalogAppQuery) (*AppsResponse, error)
- func (c *Client) GetApps(ctx context.Context, storefront string, query CatalogAppsQuery) (*AppsResponse, error)
- func (c *Client) GetBook(ctx context.Context, storefront, id string, query CatalogBookQuery) (*BooksResponse, error)
- func (c *Client) GetBooks(ctx context.Context, storefront string, query CatalogBooksQuery) (*BooksResponse, error)
- func (c *Client) GetOwnedApps(ctx context.Context, storefront string, query OwnedAppsQuery) (*ResourceCollectionResponse, error)
- func (c *Client) GetOwnedBooks(ctx context.Context, storefront string, query OwnedBooksQuery) (*ResourceCollectionResponse, error)
- func (c *Client) GetStorefront(ctx context.Context, id string, query StorefrontQuery) (*StorefrontsResponse, error)
- func (c *Client) GetStorefronts(ctx context.Context, query StorefrontsQuery) (*StorefrontsResponse, error)
- func (c *Client) Search(ctx context.Context, storefront string, query SearchQuery) (*ResultsResponse, error)
- type ContentRating
- type DescriptionAttribute
- type Error
- type ErrorsResponse
- type GenerateDeveloperTokenOptions
- type Offer
- type OfferAsset
- type OfferVersion
- type Options
- type Organization
- type OwnedAppsQuery
- type OwnedBooksQuery
- type Platform
- type Relationship
- type Resource
- type ResourceCollectionResponse
- type ResultsResponse
- type ScopedInt
- type ScopedValues
- type SearchQuery
- type SearchType
- type Storefront
- type StorefrontAttributes
- type StorefrontQuery
- type StorefrontsQuery
- type StorefrontsResponse
- type UnauthorizedResponse
- type UserRating
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoDeveloperToken = errors.New("catalog: developer token is required")
ErrNoDeveloperToken indicates that a catalog endpoint was called without a developer token.
var ErrNoPlatform = errors.New("catalog: platform is required")
ErrNoPlatform indicates that a catalog request omitted Apple's required platform query parameter.
var ErrNoResourceID = errors.New("catalog: resource ID is required")
ErrNoResourceID indicates that a single-resource catalog request omitted the required resource identifier.
var ErrNoSToken = errors.New("catalog: sToken is required for this endpoint")
ErrNoSToken indicates that an sToken-authenticated endpoint was called without an sToken cookie value.
var ErrNoStorefront = errors.New("catalog: storefront is required")
ErrNoStorefront indicates that a catalog request omitted a required storefront path parameter.
Functions ¶
func GenerateDeveloperToken ¶
func GenerateDeveloperToken(keyID, teamID string, privateKeyPEM []byte, opts GenerateDeveloperTokenOptions) (string, error)
GenerateDeveloperToken creates an ES256 JWT that can be used with Apple's Apps and Books for Organizations catalog API.
Example ¶
privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
der, _ := x509.MarshalECPrivateKey(privateKey)
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: der})
token, _ := GenerateDeveloperToken("ABC123DEFG", "TEAM123456", keyPEM, GenerateDeveloperTokenOptions{
IssuedAt: time.Unix(1700000000, 0).UTC(),
ExpiresAt: time.Unix(1700003600, 0).UTC(),
})
fmt.Println(strings.Count(token, "."))
Output: 2
Types ¶
type AllStorefrontsQuery ¶
type AllStorefrontsQuery struct {
Extend ScopedValues
Include ScopedValues
Language string
Limit ScopedInt
Offset string
Platform Platform
Relate ScopedValues
}
AllStorefrontsQuery filters the paginated storefront listing endpoint.
type App ¶
type App struct {
Attributes AppAttributes `json:"attributes,omitempty"`
Href string `json:"href"`
ID string `json:"id"`
Relationships map[string]Relationship `json:"relationships,omitempty"`
Type string `json:"type"`
}
type AppAttributes ¶
type AppAttributes struct {
ArtistName string `json:"artistName,omitempty"`
Artwork *Artwork `json:"artwork,omitempty"`
ContentRatingsBySystem map[string]ContentRating `json:"contentRatingsBySystem,omitempty"`
Description *DescriptionAttribute `json:"description,omitempty"`
DeviceFamilies []string `json:"deviceFamilies,omitempty"`
GenreDisplayName string `json:"genreDisplayName,omitempty"`
GenreNames []string `json:"genreNames,omitempty"`
HasEula bool `json:"hasEula,omitempty"`
IsB2BCustomApp bool `json:"isB2BCustomApp,omitempty"`
IsFirstPartyHideableApp bool `json:"isFirstPartyHideableApp,omitempty"`
IsIOSBinaryMacOSCompatible bool `json:"isIOSBinaryMacOSCompatible,omitempty"`
IsVppDeviceBasedLicensingEnabled bool `json:"isVppDeviceBasedLicensingEnabled,omitempty"`
Name string `json:"name,omitempty"`
Offers []Offer `json:"offers,omitempty"`
PlatformAttributes map[string]AppPlatformAttributes `json:"platformAttributes,omitempty"`
SupportsDeviceSharing bool `json:"supportsDeviceSharing,omitempty"`
URL string `json:"url,omitempty"`
UserRating *UserRating `json:"userRating,omitempty"`
UsesClassKit bool `json:"usesClassKit,omitempty"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*AppAttributes) UnmarshalJSON ¶
func (a *AppAttributes) UnmarshalJSON(data []byte) error
type AppPlatformAttributes ¶
type AppPlatformAttributes struct {
Artwork *Artwork `json:"artwork,omitempty"`
BundleID string `json:"bundleId,omitempty"`
ExternalVersionID int64 `json:"externalVersionId,omitempty"`
IsVisionOSCompatible bool `json:"isVisionOSCompatible,omitempty"`
MinimumMacOSVersion string `json:"minimumMacOSVersion,omitempty"`
MinimumOSVersion string `json:"minimumOSVersion,omitempty"`
MinimumVisionOSVersion string `json:"minimumVisionOSVersion,omitempty"`
RequiredCapabilities string `json:"requiredCapabilities,omitempty"`
RequiredCapabilitiesForRealityDevice string `json:"requiredCapabilitiesForRealityDevice,omitempty"`
Seller string `json:"seller,omitempty"`
Subtitle string `json:"subtitle,omitempty"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*AppPlatformAttributes) UnmarshalJSON ¶
func (a *AppPlatformAttributes) UnmarshalJSON(data []byte) error
type AppsResponse ¶
type AppsResponse struct {
Data []App `json:"data"`
}
type Artwork ¶
type Artwork struct {
AssetToken string `json:"assetToken,omitempty"`
BGColor string `json:"bgColor,omitempty"`
Gradient json.RawMessage `json:"gradient,omitempty"`
HasP3 bool `json:"hasP3,omitempty"`
Height float64 `json:"height"`
PictureFileType string `json:"pictureFileType,omitempty"`
SupportsLayeredImage bool `json:"supportsLayeredImage,omitempty"`
TextColor1 string `json:"textColor1,omitempty"`
TextColor2 string `json:"textColor2,omitempty"`
TextColor3 string `json:"textColor3,omitempty"`
TextColor4 string `json:"textColor4,omitempty"`
URL string `json:"url"`
Width float64 `json:"width"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*Artwork) UnmarshalJSON ¶
type Book ¶
type Book struct {
Attributes BookAttributes `json:"attributes,omitempty"`
Href string `json:"href"`
ID string `json:"id"`
Relationships map[string]Relationship `json:"relationships,omitempty"`
Type string `json:"type"`
}
type BookAttributes ¶
type BookAttributes struct {
ArtistName string `json:"artistName,omitempty"`
Artwork *Artwork `json:"artwork,omitempty"`
GenreNames []string `json:"genreNames,omitempty"`
ISBN string `json:"isbn,omitempty"`
Name string `json:"name,omitempty"`
Offers []Offer `json:"offers,omitempty"`
URL string `json:"url,omitempty"`
UserRating *UserRating `json:"userRating,omitempty"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*BookAttributes) UnmarshalJSON ¶
func (b *BookAttributes) UnmarshalJSON(data []byte) error
type BooksResponse ¶
type BooksResponse struct {
Data []Book `json:"data"`
}
type CatalogAppQuery ¶
type CatalogAppQuery struct {
AdditionalPlatforms []Platform
Extend ScopedValues
Include ScopedValues
Language string
Platform Platform
Relate ScopedValues
}
CatalogAppQuery filters metadata lookup for a single app.
type CatalogAppsQuery ¶
type CatalogAppsQuery struct {
AdditionalPlatforms []Platform
Extend ScopedValues
IDs []string
Include ScopedValues
Language string
Platform Platform
Relate ScopedValues
}
CatalogAppsQuery filters metadata lookup for multiple apps.
func (CatalogAppsQuery) CatalogAppQuery ¶
func (q CatalogAppsQuery) CatalogAppQuery() CatalogAppQuery
type CatalogBookQuery ¶
type CatalogBookQuery struct {
AdditionalPlatforms []Platform
Include ScopedValues
Language string
Platform Platform
Relate ScopedValues
}
CatalogBookQuery filters metadata lookup for a single book.
type CatalogBooksQuery ¶
type CatalogBooksQuery struct {
AdditionalPlatforms []Platform
IDs []string
Include ScopedValues
Language string
Platform Platform
Relate ScopedValues
}
CatalogBooksQuery filters metadata lookup for multiple books.
func (CatalogBooksQuery) CatalogBookQuery ¶
func (q CatalogBooksQuery) CatalogBookQuery() CatalogBookQuery
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps Apple's Apps and Books for Organizations catalog API.
func NewClient ¶
NewClient constructs a catalog client.
The developer token may be provided either as the first argument or through Options.DeveloperToken.
func (*Client) GetAllStorefronts ¶
func (c *Client) GetAllStorefronts(ctx context.Context, query AllStorefrontsQuery) (*StorefrontsResponse, error)
GetAllStorefronts returns a page of storefronts using Apple's paginated storefront listing endpoint.
func (*Client) GetApp ¶
func (c *Client) GetApp(ctx context.Context, storefront, id string, query CatalogAppQuery) (*AppsResponse, error)
GetApp returns metadata for a single app in a storefront.
Example ¶
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_ = json.NewEncoder(w).Encode(AppsResponse{
Data: []App{{ID: "623592465", Type: "apps", Href: "/v1/catalog/us/apps/623592465"}},
})
}))
defer server.Close()
client, _ := NewClient("developer-token", Options{BaseURL: server.URL})
resp, _ := client.GetApp(context.Background(), "us", "623592465", CatalogAppQuery{
Platform: PlatformIPhone,
})
fmt.Println(resp.Data[0].ID)
Output: 623592465
func (*Client) GetApps ¶
func (c *Client) GetApps(ctx context.Context, storefront string, query CatalogAppsQuery) (*AppsResponse, error)
GetApps returns metadata for multiple apps in a storefront.
func (*Client) GetBook ¶
func (c *Client) GetBook(ctx context.Context, storefront, id string, query CatalogBookQuery) (*BooksResponse, error)
GetBook returns metadata for a single book in a storefront.
func (*Client) GetBooks ¶
func (c *Client) GetBooks(ctx context.Context, storefront string, query CatalogBooksQuery) (*BooksResponse, error)
GetBooks returns metadata for multiple books in a storefront.
func (*Client) GetOwnedApps ¶
func (c *Client) GetOwnedApps(ctx context.Context, storefront string, query OwnedAppsQuery) (*ResourceCollectionResponse, error)
GetOwnedApps returns the apps visible to the current organization for the supplied storefront and sToken.
func (*Client) GetOwnedBooks ¶
func (c *Client) GetOwnedBooks(ctx context.Context, storefront string, query OwnedBooksQuery) (*ResourceCollectionResponse, error)
GetOwnedBooks returns the books visible to the current organization for the supplied storefront and sToken.
func (*Client) GetStorefront ¶
func (c *Client) GetStorefront(ctx context.Context, id string, query StorefrontQuery) (*StorefrontsResponse, error)
GetStorefront returns metadata for a single storefront.
func (*Client) GetStorefronts ¶
func (c *Client) GetStorefronts(ctx context.Context, query StorefrontsQuery) (*StorefrontsResponse, error)
GetStorefronts returns metadata for specific storefront IDs.
func (*Client) Search ¶
func (c *Client) Search(ctx context.Context, storefront string, query SearchQuery) (*ResultsResponse, error)
Search runs a storefront catalog search for apps or books.
Example ¶
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_ = json.NewEncoder(w).Encode(ResultsResponse{
Results: map[string][]Resource{
"apps": {{
ID: "623592465",
Type: "apps",
}},
},
})
}))
defer server.Close()
client, _ := NewClient("developer-token", Options{BaseURL: server.URL})
resp, _ := client.Search(context.Background(), "us", SearchQuery{
Platform: PlatformIPhone,
Term: "Numbers",
Types: []SearchType{SearchTypeApps},
})
fmt.Println(len(resp.Results["apps"]))
Output: 1
type ContentRating ¶
type DescriptionAttribute ¶
type ErrorsResponse ¶
type ErrorsResponse struct {
Errors []Error `json:"errors"`
}
type GenerateDeveloperTokenOptions ¶
type GenerateDeveloperTokenOptions struct {
IssuedAt time.Time
ExpiresAt time.Time
Origins []string
}
GenerateDeveloperTokenOptions controls the issued-at, expiration, and origin claims embedded in a developer token.
type Offer ¶
type Offer struct {
ActionText map[string]string `json:"actionText,omitempty"`
Assets []OfferAsset `json:"assets,omitempty"`
BuyParams string `json:"buyParams,omitempty"`
CurrencyCode string `json:"currencyCode,omitempty"`
Price float64 `json:"price,omitempty"`
PriceFormatted string `json:"priceFormatted,omitempty"`
PricePerUnit float64 `json:"pricePerUnit,omitempty"`
PricePerUnitFormatted string `json:"pricePerUnitFormatted,omitempty"`
Quantity int `json:"quantity,omitempty"`
Type string `json:"type,omitempty"`
Version *OfferVersion `json:"version,omitempty"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*Offer) UnmarshalJSON ¶
type OfferAsset ¶
type OfferVersion ¶
type Options ¶
type Options struct {
BaseURL string
HTTPClient *http.Client
Organization Organization
DeveloperToken string
SToken string
UserAgent string
Now func() time.Time
}
Options configures a catalog client.
type Organization ¶
type Organization string
Organization selects the Apple catalog host family.
const ( OrganizationEnterprise Organization = "enterprise" OrganizationEducation Organization = "education" )
type OwnedAppsQuery ¶
type OwnedAppsQuery struct {
AdditionalPlatforms []Platform
Extend ScopedValues
IDs []string
Language string
Platform Platform
}
OwnedAppsQuery filters sToken-authenticated owned app lookups.
type OwnedBooksQuery ¶
type OwnedBooksQuery struct {
AdditionalPlatforms []Platform
IDs []string
Language string
Platform Platform
}
OwnedBooksQuery filters sToken-authenticated owned book lookups.
type Platform ¶
type Platform string
Platform identifies the target Apple platform for catalog queries.
type Relationship ¶
type Relationship struct {
Data []Resource `json:"data,omitempty"`
Href string `json:"href,omitempty"`
Meta map[string]json.RawMessage `json:"meta,omitempty"`
Next string `json:"next,omitempty"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*Relationship) UnmarshalJSON ¶
func (r *Relationship) UnmarshalJSON(data []byte) error
type Resource ¶
type Resource struct {
Attributes json.RawMessage `json:"attributes,omitempty"`
Href string `json:"href,omitempty"`
ID string `json:"id"`
Meta map[string]json.RawMessage `json:"meta,omitempty"`
Relationships map[string]Relationship `json:"relationships,omitempty"`
Type string `json:"type"`
Views map[string]json.RawMessage `json:"views,omitempty"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*Resource) UnmarshalJSON ¶
type ResourceCollectionResponse ¶
type ResourceCollectionResponse struct {
Data []Resource `json:"data"`
}
type ResultsResponse ¶
type ScopedValues ¶
type SearchQuery ¶
type SearchQuery struct {
AdditionalPlatforms []Platform
Extend ScopedValues
Filter ScopedValues
Language string
Platform Platform
Term string
Types []SearchType
}
SearchQuery filters a storefront catalog search.
type SearchType ¶
type SearchType string
SearchType filters catalog search results by resource kind.
const ( SearchTypeApps SearchType = "apps" SearchTypeBooks SearchType = "books" )
type Storefront ¶
type Storefront struct {
Attributes StorefrontAttributes `json:"attributes,omitempty"`
Href string `json:"href"`
ID string `json:"id"`
Type string `json:"type"`
}
type StorefrontAttributes ¶
type StorefrontAttributes struct {
DefaultLanguageTag string `json:"defaultLanguageTag,omitempty"`
Name string `json:"name,omitempty"`
SupportedLanguageTags []string `json:"supportedLanguageTags,omitempty"`
Unknown map[string]json.RawMessage `json:"-"`
}
func (*StorefrontAttributes) UnmarshalJSON ¶
func (s *StorefrontAttributes) UnmarshalJSON(data []byte) error
type StorefrontQuery ¶
type StorefrontQuery struct {
Extend ScopedValues
Include ScopedValues
Language string
Platform Platform
Relate ScopedValues
}
StorefrontQuery filters metadata lookup for a single storefront.
type StorefrontsQuery ¶
type StorefrontsQuery struct {
Extend ScopedValues
IDs []string
Include ScopedValues
Language string
Platform Platform
Relate ScopedValues
}
StorefrontsQuery filters metadata lookup for specific storefront IDs.
func (StorefrontsQuery) StorefrontQuery ¶
func (q StorefrontsQuery) StorefrontQuery() StorefrontQuery
type StorefrontsResponse ¶
type StorefrontsResponse struct {
Data []Storefront `json:"data"`
}
type UnauthorizedResponse ¶
type UnauthorizedResponse struct{}