axm

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2025 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ScopeBusinessAPI = "business.api"
	ScopeSchoolAPI   = "school.api"
)

OAuth scope constants

View Source
const (
	DefaultOAuthTokenURL = "https://account.apple.com/auth/oauth2/token"
	DefaultOAuthAudience = "https://account.apple.com/auth/oauth2/v2/token"
)

Default OAuth endpoints

Variables

View Source
var (
	ErrNoNextPage      = fmt.Errorf("no next page available")
	ErrInvalidCursor   = fmt.Errorf("invalid pagination cursor")
	ErrAuthFailed      = fmt.Errorf("authentication failed")
	ErrRateLimited     = fmt.Errorf("rate limit exceeded")
	ErrInvalidResponse = fmt.Errorf("invalid response format")
)

Common error types

Functions

func HasNextPage

func HasNextPage(links *Links) bool

HasNextPage checks if there is a next page available

func HasPrevPage

func HasPrevPage(links *Links) bool

HasPrevPage checks if there is a previous page available

func LoadPrivateKeyFromEnv

func LoadPrivateKeyFromEnv() (any, error)

LoadPrivateKeyFromEnv loads a private key from the environment variable APPLE_PRIVATE_KEY_PATH

func LoadPrivateKeyFromFile

func LoadPrivateKeyFromFile(filePath string) (any, error)

LoadPrivateKeyFromFile loads a private key (RSA or ECDSA) from a PEM file

func ParsePrivateKey

func ParsePrivateKey(keyData []byte) (any, error)

ParsePrivateKey parses a private key (RSA or ECDSA) from PEM-encoded data

func ValidatePrivateKey

func ValidatePrivateKey(privateKey any) error

ValidatePrivateKey validates that the private key is suitable for JWT signing

Types

type APIError

type APIError struct {
	ID     string          `json:"id,omitempty"`
	Status string          `json:"status"`
	Code   string          `json:"code"`
	Title  string          `json:"title"`
	Detail string          `json:"detail"`
	Source *APIErrorSource `json:"source,omitempty"`
	Links  *ErrorLinks     `json:"links,omitempty"`
	Meta   *APIErrorMeta   `json:"meta,omitempty"`
}

APIError represents a single error from the Apple Business Manager API

func (*APIError) Error

func (e *APIError) Error() string

type APIErrorMeta

type APIErrorMeta struct {
	// Can contain any key-value pairs as specified in the API documentation
	AdditionalProperties map[string]any `json:"-"`
}

APIErrorMeta contains additional error metadata

func (*APIErrorMeta) MarshalJSON

func (m *APIErrorMeta) MarshalJSON() ([]byte, error)

MarshalJSON implements custom marshaling for APIErrorMeta

func (*APIErrorMeta) UnmarshalJSON

func (m *APIErrorMeta) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom unmarshaling for APIErrorMeta

type APIErrorResponse

type APIErrorResponse struct {
	ErrorCode string         `json:"error_code"`
	Message   string         `json:"message"`
	Details   map[string]any `json:"details,omitempty"`
}

APIErrorResponse represents the legacy error structure (keeping for backward compatibility)

type APIErrorSource

type APIErrorSource struct {
	JsonPointer *JsonPointer `json:"jsonPointer,omitempty"`
	Parameter   *Parameter   `json:"parameter,omitempty"`
}

APIErrorSource represents the source of an error (JsonPointer or Parameter)

type APIKeyAuth

type APIKeyAuth struct {
	// contains filtered or unexported fields
}

APIKeyAuth implements simple API key authentication

func NewAPIKeyAuth

func NewAPIKeyAuth(apiKey, header string) *APIKeyAuth

NewAPIKeyAuth creates a new API key authentication provider

func (*APIKeyAuth) ApplyAuth

func (a *APIKeyAuth) ApplyAuth(req *resty.Request) error

ApplyAuth applies API key authentication to the request

type APIResponse

type APIResponse[T any] struct {
	Data  []T   `json:"data"`
	Meta  Meta  `json:"meta"`
	Links Links `json:"links"`
}

APIResponse represents the standard API response structure

type AuthProvider

type AuthProvider interface {
	ApplyAuth(req *resty.Request) error
}

AuthProvider interface for different authentication methods

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client represents the main Apple Business Manager API client

func NewClient

func NewClient(config Config) (*Client, error)

NewClient creates a new Apple Business Manager API client

func NewClientFromEnv

func NewClientFromEnv() (*Client, error)

NewClientFromEnv creates an AXM client using environment variables Expects: APPLE_KEY_ID, APPLE_ISSUER_ID, APPLE_PRIVATE_KEY_PATH

func NewClientFromEnvWithOptions

func NewClientFromEnvWithOptions(debug bool, timeout time.Duration, userAgent string) (*Client, error)

NewClientFromEnvWithOptions creates an AXM client from environment variables with custom options

func NewClientFromFile

func NewClientFromFile(keyID, issuerID, privateKeyPath string) (*Client, error)

NewClientFromFile creates an AXM client using credentials from files

func NewClientFromFileWithOptions

func NewClientFromFileWithOptions(keyID, issuerID, privateKeyPath string, debug bool, timeout time.Duration, userAgent string) (*Client, error)

NewClientFromFileWithOptions creates an AXM client from files with custom options

func (*Client) Close

func (c *Client) Close() error

Close closes the HTTP client and cleans up resources

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, path string, queryParams map[string]string, headers map[string]string, result any) error

Delete executes a DELETE request following Resty v3 best practices. Supports query parameters for filtering or specifying deletion criteria.

This method uses Resty's SetQueryParam for URL parameters and follows RESTful conventions for resource deletion operations.

Reference: https://resty.dev/docs/request-query-params/ Reference: https://resty.dev/docs/response-auto-parse/

func (*Client) DeleteWithBody

func (c *Client) DeleteWithBody(ctx context.Context, path string, body any, headers map[string]string, result any) error

DeleteWithBody executes a DELETE request with body (for bulk operations). Useful for bulk deletion operations where multiple resources are specified in the request body.

While not always RESTful, some APIs require request bodies for DELETE operations to specify multiple resources or complex deletion criteria.

Reference: https://resty.dev/docs/request-body-types/

func (*Client) Get

func (c *Client) Get(ctx context.Context, path string, queryParams map[string]string, headers map[string]string, result any) error

Get executes a GET request following Resty v3 best practices. Supports query parameters, custom headers, and automatic response parsing.

This method uses Resty's SetQueryParam for URL parameters and SetHeader for custom headers. The response is automatically unmarshaled into the provided result interface{}.

Reference: https://resty.dev/docs/request-query-params/ Reference: https://resty.dev/docs/response-auto-parse/

func (*Client) GetAllPages

func (c *Client) GetAllPages(ctx context.Context, path string, queryParams map[string]string, headers map[string]string, processPage func([]byte) error) error

GetAllPages retrieves all pages of results by following pagination links

func (*Client) GetHTTPClient

func (c *Client) GetHTTPClient() *resty.Client

GetHTTPClient returns the underlying HTTP client for testing purposes

func (*Client) GetNextPage

func (c *Client) GetNextPage(ctx context.Context, nextURL string, headers map[string]string, result any) error

GetNextPage extracts the next page URL from links and makes a request

func (*Client) GetPaginated

func (c *Client) GetPaginated(ctx context.Context, path string, queryParams map[string]string, headers map[string]string, result any) error

GetPaginated executes a paginated GET request

func (*Client) Patch

func (c *Client) Patch(ctx context.Context, path string, body any, headers map[string]string, result any) error

Patch executes a PATCH request following Resty v3 best practices. Typically used for partial updates of existing resources.

The body parameter is automatically marshaled to JSON using Resty's SetBody method. Follows RESTful conventions for partial resource modifications.

Reference: https://resty.dev/docs/request-body-types/ Reference: https://resty.dev/docs/response-auto-parse/

func (*Client) Post

func (c *Client) Post(ctx context.Context, path string, body any, headers map[string]string, result any) error

Post executes a POST request with JSON body following Resty v3 best practices. Automatically sets Content-Type to application/json and handles request body serialization.

The body parameter is automatically marshaled to JSON using Resty's SetBody method. Custom headers can be provided to override defaults or add additional headers.

Reference: https://resty.dev/docs/request-body-types/ Reference: https://resty.dev/docs/response-auto-parse/

func (*Client) PostMultipart

func (c *Client) PostMultipart(ctx context.Context, path string, files map[string]string, fields map[string]string, result any) error

PostMultipart executes a POST request with multipart form data following Resty v3 best practices. Supports file uploads and form fields in a single multipart/form-data request.

This method uses Resty's SetFile for file uploads and SetFormData for form fields. Automatically sets the appropriate Content-Type header for multipart requests.

Files map: fieldName -> filePath Fields map: fieldName -> fieldValue

Reference: https://resty.dev/docs/multipart/ Reference: https://resty.dev/docs/form-data/

func (*Client) PostWithQuery

func (c *Client) PostWithQuery(ctx context.Context, path string, queryParams map[string]string, body any, headers map[string]string, result any) error

PostWithQuery executes a POST request with both body and query parameters. Combines the functionality of POST requests with URL query parameter support.

This method is useful for APIs that require both request body data and URL parameters. The body is JSON-serialized while query parameters are added to the URL.

Reference: https://resty.dev/docs/request-query-params/ Reference: https://resty.dev/docs/request-body-types/

func (*Client) Put

func (c *Client) Put(ctx context.Context, path string, body any, headers map[string]string, result any) error

Put executes a PUT request following Resty v3 best practices. Typically used for updating existing resources with complete replacement.

The body parameter is automatically marshaled to JSON using Resty's SetBody method. Follows RESTful conventions for resource updates and modifications.

Reference: https://resty.dev/docs/request-body-types/ Reference: https://resty.dev/docs/response-auto-parse/

func (*Client) QueryBuilder

func (c *Client) QueryBuilder() *QueryBuilder

QueryBuilder returns a new query builder instance

type ClientBuilder

type ClientBuilder struct {
	// contains filtered or unexported fields
}

ClientBuilder provides a fluent interface for building AXM clients

func NewClientBuilder

func NewClientBuilder() *ClientBuilder

NewClientBuilder creates a new client builder with default values

func (*ClientBuilder) Build

func (cb *ClientBuilder) Build() (*Client, error)

Build creates and returns the configured AXM client

func (*ClientBuilder) Clone

func (cb *ClientBuilder) Clone() *ClientBuilder

Clone creates a copy of the client builder

func (*ClientBuilder) MustBuild

func (cb *ClientBuilder) MustBuild() *Client

MustBuild creates the AXM client and panics if there's an error Use this only when you're certain the configuration is valid

func (*ClientBuilder) Validate

func (cb *ClientBuilder) Validate() error

Validate checks the current configuration without building the client

func (*ClientBuilder) WithAudience

func (cb *ClientBuilder) WithAudience(audience string) *ClientBuilder

WithAudience sets the JWT audience (default: appstoreconnect-v1)

func (*ClientBuilder) WithBaseURL

func (cb *ClientBuilder) WithBaseURL(baseURL string) *ClientBuilder

WithBaseURL sets the base URL for the API (default: https://api-business.apple.com/v1)

func (*ClientBuilder) WithDebug

func (cb *ClientBuilder) WithDebug(debug bool) *ClientBuilder

WithDebug enables or disables debug mode (default: false)

func (*ClientBuilder) WithJWTAuth

func (cb *ClientBuilder) WithJWTAuth(keyID, issuerID string, privateKey any) *ClientBuilder

WithJWTAuth configures JWT authentication with provided credentials

func (*ClientBuilder) WithJWTAuthFromEnv

func (cb *ClientBuilder) WithJWTAuthFromEnv() *ClientBuilder

WithJWTAuthFromEnv configures JWT authentication from environment variables Expects: APPLE_KEY_ID, APPLE_ISSUER_ID, APPLE_PRIVATE_KEY_PATH

func (*ClientBuilder) WithJWTAuthFromFile

func (cb *ClientBuilder) WithJWTAuthFromFile(keyID, issuerID, privateKeyPath string) *ClientBuilder

WithJWTAuthFromFile configures JWT authentication from a private key file

func (*ClientBuilder) WithLogger

func (cb *ClientBuilder) WithLogger(logger *zap.Logger) *ClientBuilder

WithLogger sets a custom logger (default: no-op logger, or development logger if debug is enabled)

func (*ClientBuilder) WithRetry

func (cb *ClientBuilder) WithRetry(count int, wait time.Duration) *ClientBuilder

WithRetry configures retry settings (default: 3 retries, 1 second wait)

func (*ClientBuilder) WithTimeout

func (cb *ClientBuilder) WithTimeout(timeout time.Duration) *ClientBuilder

WithTimeout sets the request timeout (default: 30 seconds)

func (*ClientBuilder) WithUserAgent

func (cb *ClientBuilder) WithUserAgent(userAgent string) *ClientBuilder

WithUserAgent sets the user agent string (default: go-api-sdk-apple/1.0.0)

type Config

type Config struct {
	BaseURL    string
	Auth       AuthProvider
	Logger     *zap.Logger
	Timeout    time.Duration
	RetryCount int
	RetryWait  time.Duration
	UserAgent  string
	Debug      bool
}

Config holds configuration for the client

type ErrorHandler

type ErrorHandler struct {
	// contains filtered or unexported fields
}

ErrorHandler centralizes error handling for all API requests

func NewErrorHandler

func NewErrorHandler(logger *zap.Logger) *ErrorHandler

NewErrorHandler creates a new error handler

func (*ErrorHandler) HandleError

func (eh *ErrorHandler) HandleError(resp *resty.Response, errorResp *ErrorResponse) error

HandleError processes API error responses and returns structured errors

type ErrorLinks struct {
	About      string                `json:"about,omitempty"`
	Associated *ErrorLinksAssociated `json:"associated,omitempty"`
}

ErrorLinks contains error-related links

type ErrorLinksAssociated

type ErrorLinksAssociated struct {
	Href string                    `json:"href"`
	Meta *ErrorLinksAssociatedMeta `json:"meta,omitempty"`
}

ErrorLinksAssociated represents associated error links

type ErrorLinksAssociatedMeta

type ErrorLinksAssociatedMeta struct {
	// Can contain any key-value pairs as specified in the API
	AdditionalProperties map[string]any `json:"-"`
}

ErrorLinksAssociatedMeta contains metadata for associated error links

func (*ErrorLinksAssociatedMeta) MarshalJSON

func (m *ErrorLinksAssociatedMeta) MarshalJSON() ([]byte, error)

MarshalJSON implements custom marshaling for ErrorLinksAssociatedMeta

func (*ErrorLinksAssociatedMeta) UnmarshalJSON

func (m *ErrorLinksAssociatedMeta) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom unmarshaling for ErrorLinksAssociatedMeta

type ErrorResponse

type ErrorResponse struct {
	Errors []APIError `json:"errors"`
}

ErrorResponse represents the complete error response structure returned by the API

type JWTAuth

type JWTAuth struct {
	// contains filtered or unexported fields
}

JWTAuth implements OAuth 2.0 JWT-based authentication for Apple Business Manager API

func NewJWTAuth

func NewJWTAuth(config JWTAuthConfig) *JWTAuth

NewJWTAuth creates a new OAuth 2.0 JWT authentication provider

func (*JWTAuth) ApplyAuth

func (j *JWTAuth) ApplyAuth(req *resty.Request) error

ApplyAuth applies OAuth 2.0 authentication to the request

type JWTAuthConfig

type JWTAuthConfig struct {
	KeyID      string
	IssuerID   string
	PrivateKey any    // Can be *rsa.PrivateKey or *ecdsa.PrivateKey
	Audience   string // Usually "appstoreconnect-v1"
	Scope      string // "business.api" or "school.api"
}

JWTAuthConfig holds configuration for JWT authentication

type JsonPointer

type JsonPointer struct {
	Pointer string `json:"pointer"`
}

JsonPointer represents a JSON pointer source

type Links struct {
	Self  string `json:"self,omitempty"`
	First string `json:"first,omitempty"`
	Next  string `json:"next,omitempty"`
	Prev  string `json:"prev,omitempty"`
	Last  string `json:"last,omitempty"`
}

Links contains pagination navigation links matching Apple's API format

type Meta

type Meta struct {
	Paging *Paging `json:"paging,omitempty"`
}

Meta contains pagination metadata matching Apple's API format

type OAuth2Auth

type OAuth2Auth struct {
	// contains filtered or unexported fields
}

OAuth2Auth implements OAuth 2.0 authentication for Apple School and Business Manager API

func NewOAuth2Auth

func NewOAuth2Auth(config OAuth2Config) (*OAuth2Auth, error)

NewOAuth2Auth creates a new OAuth 2.0 authentication provider

func (*OAuth2Auth) ApplyAuth

func (o *OAuth2Auth) ApplyAuth(req *resty.Request) error

ApplyAuth applies OAuth 2.0 authentication to the request

func (*OAuth2Auth) ForceRefresh

func (o *OAuth2Auth) ForceRefresh()

ForceRefresh forces a token refresh on the next request

func (*OAuth2Auth) GetTokenInfo

func (o *OAuth2Auth) GetTokenInfo() TokenInfo

GetTokenInfo returns information about the current access token

type OAuth2Config

type OAuth2Config struct {
	ClientID   string            // Your client ID from Apple
	TeamID     string            // Your team ID
	KeyID      string            // Your key ID from Apple
	PrivateKey *ecdsa.PrivateKey // Your ECDSA private key
	Scope      string            // "business.api" or "school.api"
	TokenURL   string            // OAuth token endpoint (optional, defaults to Apple's)
	HTTPClient *resty.Client     // HTTP client for token requests (optional)
}

OAuth2Config holds configuration for OAuth 2.0 authentication

type OAuth2TokenResponse

type OAuth2TokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
	Scope       string `json:"scope"`
}

OAuth2TokenResponse represents the OAuth 2.0 token response

type PaginationOptions

type PaginationOptions struct {
	Limit  int    `json:"limit,omitempty"`
	Cursor string `json:"cursor,omitempty"`
}

PaginationOptions represents common pagination parameters for Apple's API

func (*PaginationOptions) AddToQueryBuilder

func (opts *PaginationOptions) AddToQueryBuilder(qb *QueryBuilder) *QueryBuilder

AddToQueryBuilder adds pagination options to a query builder

type Paging

type Paging struct {
	Total      int    `json:"total,omitempty"`
	Limit      int    `json:"limit,omitempty"`
	NextCursor string `json:"nextCursor,omitempty"`
}

Paging contains pagination information matching Apple's API format

type Parameter

type Parameter struct {
	Parameter string `json:"parameter"`
}

Parameter represents a query parameter source

type QueryBuilder

type QueryBuilder struct {
	// contains filtered or unexported fields
}

QueryBuilder provides a fluent interface for building query parameters

func NewQueryBuilder

func NewQueryBuilder() *QueryBuilder

NewQueryBuilder creates a new query builder

func (*QueryBuilder) AddBool

func (qb *QueryBuilder) AddBool(key string, value bool) *QueryBuilder

AddBool adds a boolean parameter

func (*QueryBuilder) AddCustom

func (qb *QueryBuilder) AddCustom(key, value string) *QueryBuilder

AddCustom adds a custom parameter with any value

func (*QueryBuilder) AddIfNotEmpty

func (qb *QueryBuilder) AddIfNotEmpty(key, value string) *QueryBuilder

AddIfNotEmpty adds a parameter only if the value is not empty

func (*QueryBuilder) AddIfTrue

func (qb *QueryBuilder) AddIfTrue(condition bool, key, value string) *QueryBuilder

AddIfTrue adds a parameter only if the condition is true

func (*QueryBuilder) AddInt

func (qb *QueryBuilder) AddInt(key string, value int) *QueryBuilder

AddInt adds an integer parameter if the value is greater than 0

func (*QueryBuilder) AddInt64

func (qb *QueryBuilder) AddInt64(key string, value int64) *QueryBuilder

AddInt64 adds an int64 parameter if the value is greater than 0

func (*QueryBuilder) AddIntSlice

func (qb *QueryBuilder) AddIntSlice(key string, values []int) *QueryBuilder

AddIntSlice adds an integer slice parameter as comma-separated values

func (*QueryBuilder) AddString

func (qb *QueryBuilder) AddString(key, value string) *QueryBuilder

AddString adds a string parameter if the value is not empty

func (*QueryBuilder) AddStringSlice

func (qb *QueryBuilder) AddStringSlice(key string, values []string) *QueryBuilder

AddStringSlice adds a string slice parameter as comma-separated values

func (*QueryBuilder) AddTime

func (qb *QueryBuilder) AddTime(key string, value time.Time) *QueryBuilder

AddTime adds a time parameter in RFC3339 format if the time is not zero

func (*QueryBuilder) Build

func (qb *QueryBuilder) Build() map[string]string

Build returns the final map of query parameters

func (*QueryBuilder) BuildString

func (qb *QueryBuilder) BuildString() string

BuildString returns the query parameters as a URL-encoded string

func (*QueryBuilder) Clear

func (qb *QueryBuilder) Clear() *QueryBuilder

Clear removes all parameters

func (*QueryBuilder) Count

func (qb *QueryBuilder) Count() int

Count returns the number of parameters

func (*QueryBuilder) Get

func (qb *QueryBuilder) Get(key string) string

Get retrieves a parameter value

func (*QueryBuilder) Has

func (qb *QueryBuilder) Has(key string) bool

Has checks if a parameter exists

func (*QueryBuilder) IsEmpty

func (qb *QueryBuilder) IsEmpty() bool

IsEmpty returns true if no parameters are set

func (*QueryBuilder) Merge

func (qb *QueryBuilder) Merge(other map[string]string) *QueryBuilder

Merge merges parameters from another query builder or map

func (*QueryBuilder) Remove

func (qb *QueryBuilder) Remove(key string) *QueryBuilder

Remove removes a parameter

type TokenInfo

type TokenInfo struct {
	HasToken     bool      `json:"has_token"`
	ExpiresAt    time.Time `json:"expires_at,omitempty"`
	ExpiresIn    int64     `json:"expires_in,omitempty"`
	IsExpired    bool      `json:"is_expired"`
	NeedsRefresh bool      `json:"needs_refresh"`
}

TokenInfo represents information about the current access token

type TokenResponse

type TokenResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
	Scope       string `json:"scope"`
}

TokenResponse represents the OAuth 2.0 token response from Apple

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL