[GH-ISSUE #26] Phase 8: Analytics and sales reports #4

Closed
opened 2026-02-26 21:32:43 +03:00 by kerem · 1 comment
Owner

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

PRD: Analytics and Sales Reports in ASC CLI

Overview

This PRD outlines the implementation of analytics and sales reporting commands for App Store Connect CLI, enabling developers and AI agents to download sales reports, request analytics reports, and retrieve usage metrics programmatically.

Goals

  1. Enable developers to download sales and trends reports via CLI
  2. Support requesting and retrieving analytics reports (usage metrics, engagement data)
  3. Provide programmatic access to over 50 analytics report types
  4. Maintain AI-first design with JSON output by default
  5. Follow explicit, non-interactive CLI patterns
  6. Handle GZIP-compressed report files appropriately

API Endpoints

Method Endpoint Description
GET /v1/salesReports Download sales and trends reports (returns GZIP file)

Query Parameters:

  • filter[vendorNumber] (required) - Vendor number for your developer account
  • filter[reportType] (required) - Report type: SALES, PRE_ORDER, NEWSSTAND, SUBSCRIPTION, SUBSCRIPTION_EVENT
  • filter[reportSubType] (required) - Report detail level: SUMMARY, DETAILED
  • filter[frequency] (required) - Time interval: DAILY, WEEKLY, MONTHLY, YEARLY
  • filter[reportDate] (required) - Report date in YYYY-MM-DD format
  • filter[version] (optional) - Report format version: 1_0 (default), 1_1

Response: GZIP-compressed TSV file (binary)

Analytics Reports (Multi-Step Workflow)

Method Endpoint Description
POST /v1/analyticsReportRequests Create a new analytics report request
GET /v1/analyticsReportRequests List analytics report requests
GET /v1/analyticsReportRequests/{id} Get specific report request details
GET /v1/analyticsReports List analytics reports for a request
GET /v1/analyticsReportInstances List report instances (by date/version)
GET /v1/analyticsReportSegments Get report segments with download URLs

Report Categories:

  • App Store Engagement: Impressions, product page views, custom product pages, in-app events
  • App Store Commerce: Revenue, sales, proceeds
  • App Usage: Active devices, sessions, installations, deletions
  • Framework Usage: Framework and API usage data
  • Performance: Crash rates, hang rates, performance metrics

CLI Commands

Command Structure

# Sales reports
asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20" [flags]

# Analytics reports (request)
asc analytics request --app "APP_ID" --access-type ONGOING [flags]

# Analytics reports (list requests)
asc analytics requests --app "APP_ID" [flags]

# Analytics reports (get report)
asc analytics get --request-id "REQUEST_ID" [flags]

# Analytics reports (download)
asc analytics download --request-id "REQUEST_ID" --instance-id "INSTANCE_ID" [flags]

Subcommands

Downloads sales and trends reports as GZIP-compressed TSV files.

Flags:

  • --vendor (required) - Vendor number (or ASC_VENDOR_NUMBER env)
  • --type (required) - Report type: SALES, PRE_ORDER, NEWSSTAND, SUBSCRIPTION, SUBSCRIPTION_EVENT
  • --subtype (required) - Report subtype: SUMMARY, DETAILED
  • --frequency (required) - Frequency: DAILY, WEEKLY, MONTHLY, YEARLY
  • --date (required) - Report date in YYYY-MM-DD format
  • --version (optional) - Report format version: 1_0 (default), 1_1
  • --output (optional) - Output file path (default: sales_report_{date}_{type}.tsv.gz)
  • --decompress (optional) - Automatically decompress GZIP file to .tsv
  • --output-format (optional) - Output format for metadata: json (default), table, markdown
  • --pretty (optional) - Pretty-print JSON output

Examples:

# Download daily sales summary
asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20"

# Download monthly subscription report
asc analytics sales --vendor "12345678" --type SUBSCRIPTION --subtype DETAILED --frequency MONTHLY --date "2024-01-01"

# Download and decompress automatically
asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20" --decompress

# Custom output path
asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20" --output "reports/daily_sales.tsv.gz"

JSON Output (metadata):

{"vendorNumber":"12345678","reportType":"SALES","reportSubType":"SUMMARY","frequency":"DAILY","reportDate":"2024-01-20","version":"1_0","filePath":"sales_report_2024-01-20_SALES.tsv.gz","fileSize":12345,"decompressed":false}

Note: Reports are typically available the day after the report date. Monthly reports require dates aligned with Apple's reporting periods.

request - Create Analytics Report Request

Creates a new analytics report request for an app.

Flags:

  • --app (required) - App Store Connect app ID (or ASC_APP_ID env)
  • --access-type (required) - Access type: ONGOING (daily updates), ONE_TIME_SNAPSHOT (single snapshot)
  • --output (optional) - Output format: json (default), table, markdown
  • --pretty (optional) - Pretty-print JSON output

Examples:

# Create ongoing analytics report request
asc analytics request --app "123456789" --access-type ONGOING

# Create one-time snapshot
asc analytics request --app "123456789" --access-type ONE_TIME_SNAPSHOT

JSON Output:

{"requestId":"abc123def456","appId":"123456789","accessType":"ONGOING","createdDate":"2024-01-20T12:00:00Z","state":"PROCESSING"}

Note: Requires API key with Admin permissions. Analytics data may take 1-2 days to unlock after API credentials are first saved.

requests - List Analytics Report Requests

Lists analytics report requests for an app.

Flags:

  • --app (required) - App Store Connect app ID (or ASC_APP_ID env)
  • --request-id (optional) - Filter by specific request ID
  • --state (optional) - Filter by state: PROCESSING, COMPLETED, FAILED
  • --limit (optional) - Maximum results per page (1-200)
  • --next (optional) - Fetch next page using links.next URL
  • --output (optional) - Output format: json (default), table, markdown
  • --pretty (optional) - Pretty-print JSON output

Examples:

# List all requests for an app
asc analytics requests --app "123456789"

# Get specific request details
asc analytics requests --app "123456789" --request-id "abc123def456"

# Filter by state
asc analytics requests --app "123456789" --state COMPLETED

JSON Output:

{"data":[{"id":"abc123def456","type":"analyticsReportRequests","attributes":{"accessType":"ONGOING","state":"COMPLETED","createdDate":"2024-01-20T12:00:00Z"},"relationships":{"app":{"data":{"type":"apps","id":"123456789"}}}}],"links":{"self":"...","next":null}}

get - Get Analytics Reports

Retrieves analytics reports for a request, including instances and segments.

Flags:

  • --request-id (required) - Analytics report request ID
  • --instance-id (optional) - Filter by specific instance ID
  • --date (optional) - Filter instances by date (YYYY-MM-DD)
  • --include-segments (optional) - Include report segments with download URLs
  • --limit (optional) - Maximum results per page (1-200)
  • --next (optional) - Fetch next page using links.next URL
  • --output (optional) - Output format: json (default), table, markdown
  • --pretty (optional) - Pretty-print JSON output

Examples:

# Get all reports for a request
asc analytics get --request-id "abc123def456"

# Get reports with segments (download URLs)
asc analytics get --request-id "abc123def456" --include-segments

# Get specific instance
asc analytics get --request-id "abc123def456" --instance-id "instance-123"

# Filter by date
asc analytics get --request-id "abc123def456" --date "2024-01-20"

JSON Output:

{"data":[{"id":"report-123","type":"analyticsReports","attributes":{"reportType":"APP_USAGE","granularity":"DAILY"},"relationships":{"request":{"data":{"type":"analyticsReportRequests","id":"abc123def456"}},"instances":{"data":[{"type":"analyticsReportInstances","id":"instance-123"}]}},"instances":[{"id":"instance-123","date":"2024-01-20","segments":[{"id":"segment-456","downloadUrl":"https://..."}]}]}],"links":{"self":"...","next":null}}

download - Download Analytics Report

Downloads an analytics report file from a segment.

Flags:

  • --request-id (required) - Analytics report request ID
  • --instance-id (required) - Report instance ID
  • --segment-id (optional) - Specific segment ID (if multiple segments exist)
  • --output (optional) - Output file path (default: analytics_report_{requestId}_{instanceId}.csv.gz)
  • --decompress (optional) - Automatically decompress GZIP file to .csv
  • --output-format (optional) - Output format for metadata: json (default), table, markdown
  • --pretty (optional) - Pretty-print JSON output

Examples:

# Download report from instance
asc analytics download --request-id "abc123def456" --instance-id "instance-123"

# Download and decompress
asc analytics download --request-id "abc123def456" --instance-id "instance-123" --decompress

# Download specific segment
asc analytics download --request-id "abc123def456" --instance-id "instance-123" --segment-id "segment-456"

# Custom output path
asc analytics download --request-id "abc123def456" --instance-id "instance-123" --output "reports/usage_2024-01-20.csv.gz"

JSON Output (metadata):

{"requestId":"abc123def456","instanceId":"instance-123","segmentId":"segment-456","filePath":"analytics_report_abc123def456_instance-123.csv.gz","fileSize":67890,"decompressed":false,"downloadUrl":"https://..."}

Note: Report files are typically GZIP-compressed CSV files. Download URLs may expire; download promptly after retrieval.


Request/Response Shapes

Sales Reports (GET)

Request:

GET /v1/salesReports?filter[vendorNumber]=12345678&filter[reportType]=SALES&filter[reportSubType]=SUMMARY&filter[frequency]=DAILY&filter[reportDate]=2024-01-20&filter[version]=1_0

Response:

  • Content-Type: application/a-gzip or application/gzip
  • Body: Binary GZIP-compressed TSV file
  • Headers may include Content-Disposition with filename

Create Analytics Report Request (POST)

Request:

{
  "data": {
    "type": "analyticsReportRequests",
    "attributes": {
      "accessType": "ONGOING"
    },
    "relationships": {
      "app": {
        "data": {
          "type": "apps",
          "id": "123456789"
        }
      }
    }
  }
}

Response:

{
  "data": {
    "type": "analyticsReportRequests",
    "id": "abc123def456",
    "attributes": {
      "accessType": "ONGOING",
      "state": "PROCESSING",
      "createdDate": "2024-01-20T12:00:00Z"
    },
    "relationships": {
      "app": {
        "data": {
          "type": "apps",
          "id": "123456789"
        }
      }
    }
  },
  "links": {
    "self": "https://api.appstoreconnect.apple.com/v1/analyticsReportRequests/abc123def456"
  }
}

Get Analytics Reports (GET)

Request:

GET /v1/analyticsReports?filter[analyticsReportRequest]=abc123def456&include=instances,instances.segments

Response:

{
  "data": [
    {
      "type": "analyticsReports",
      "id": "report-123",
      "attributes": {
        "reportType": "APP_USAGE",
        "granularity": "DAILY"
      },
      "relationships": {
        "request": {
          "data": {
            "type": "analyticsReportRequests",
            "id": "abc123def456"
          }
        },
        "instances": {
          "data": [
            {
              "type": "analyticsReportInstances",
              "id": "instance-123"
            }
          ]
        }
      }
    }
  ],
  "included": [
    {
      "type": "analyticsReportInstances",
      "id": "instance-123",
      "attributes": {
        "date": "2024-01-20"
      },
      "relationships": {
        "segments": {
          "data": [
            {
              "type": "analyticsReportSegments",
              "id": "segment-456"
            }
          ]
        }
      }
    },
    {
      "type": "analyticsReportSegments",
      "id": "segment-456",
      "attributes": {
        "downloadUrl": "https://analytics.appstoreconnect.apple.com/..."
      }
    }
  ],
  "links": {
    "self": "https://api.appstoreconnect.apple.com/v1/analyticsReports?filter[analyticsReportRequest]=abc123def456"
  }
}

Required Fields

Sales Reports

Required Query Parameters:

  • filter[vendorNumber]: String - Vendor number (8+ digits)
  • filter[reportType]: Enum - SALES, PRE_ORDER, NEWSSTAND, SUBSCRIPTION, SUBSCRIPTION_EVENT
  • filter[reportSubType]: Enum - SUMMARY, DETAILED
  • filter[frequency]: Enum - DAILY, WEEKLY, MONTHLY, YEARLY
  • filter[reportDate]: String - Date in YYYY-MM-DD format

Optional Query Parameters:

  • filter[version]: String - Report format version: 1_0 (default), 1_1

Analytics Report Requests

Required Fields:

  • type: "analyticsReportRequests"
  • attributes.accessType: Enum - ONGOING, ONE_TIME_SNAPSHOT
  • relationships.app.data.type: "apps"
  • relationships.app.data.id: String - App ID (UUID)

Validation

Input Validation

  1. Vendor Number

    • Required for sales command
    • Must be numeric string (8+ digits)
    • Can be provided via --vendor flag or ASC_VENDOR_NUMBER environment variable
  2. Report Type

    • Required for sales command
    • Valid values: SALES, PRE_ORDER, NEWSSTAND, SUBSCRIPTION, SUBSCRIPTION_EVENT
    • Case-insensitive (normalize to uppercase)
  3. Report Subtype

    • Required for sales command
    • Valid values: SUMMARY, DETAILED
    • Case-insensitive (normalize to uppercase)
  4. Frequency

    • Required for sales command
    • Valid values: DAILY, WEEKLY, MONTHLY, YEARLY
    • Case-insensitive (normalize to uppercase)
  5. Report Date

    • Required for sales command
    • Format: YYYY-MM-DD (ISO 8601 date)
    • Must be valid date
    • For monthly reports, must align with Apple's reporting periods (typically first day of month)
  6. Version

    • Optional for sales command
    • Valid values: 1_0 (default), 1_1
    • Format: {major}_{minor}
  7. App ID

    • Required for request and requests commands
    • Must be valid UUID format
    • Can be provided via --app flag or ASC_APP_ID environment variable
  8. Access Type

    • Required for request command
    • Valid values: ONGOING, ONE_TIME_SNAPSHOT
    • Case-insensitive (normalize to uppercase)
  9. Request ID

    • Required for get and download commands
    • Must be valid UUID format
  10. Instance ID

    • Required for download command
    • Must be valid UUID format
  11. Segment ID

    • Optional for download command
    • Must be valid UUID format
    • If not provided and multiple segments exist, download first segment
  12. Limit

    • Must be between 1 and 200 if provided
    • Default: API default (typically 50)

Date Validation

  1. Report Date Format

    • Must match YYYY-MM-DD format
    • Validate using Go's time.Parse("2006-01-02", date)
  2. Monthly Report Dates

    • Monthly reports typically require dates on the first day of the month
    • Validate and warn if date is not first of month for monthly frequency
  3. Future Dates

    • Sales reports are typically available the day after the report date
    • Warn if requesting future dates or dates too far in the past

Error Handling

Common Errors

  1. Invalid Vendor Number

    Error: invalid vendor number "INVALID"
    Vendor number must be numeric and 8+ digits
    
  2. Invalid Report Type

    Error: invalid report type "INVALID"
    Valid types: SALES, PRE_ORDER, NEWSSTAND, SUBSCRIPTION, SUBSCRIPTION_EVENT
    
  3. Invalid Frequency

    Error: invalid frequency "INVALID"
    Valid frequencies: DAILY, WEEKLY, MONTHLY, YEARLY
    
  4. Invalid Date Format

    Error: invalid date format "2024/01/20"
    Date must be in YYYY-MM-DD format
    
  5. Report Not Available

    Error: report not available for date "2024-01-20"
    Reports are typically available the day after the report date
    
  6. Monthly Report Date Mismatch

    Error: monthly reports require dates on the first day of the month
    Provided: 2024-01-15, Expected: 2024-01-01
    
  7. Request Not Found

    Error: analytics report request not found for ID "abc123def456"
    
  8. Report Not Ready

    Error: analytics report request is still processing
    Request ID: abc123def456, State: PROCESSING
    Wait for state to become COMPLETED before downloading
    
  9. Download URL Expired

    Error: download URL has expired
    Request a new report instance to get a fresh download URL
    
  10. Unauthorized

    Error: unauthorized. Check your API credentials.
    Analytics reports require Admin permissions
    
  11. Rate Limiting

    Error: rate limit exceeded. Please try again later.
    
  12. File Write Error

    Error: failed to write report file to "reports/sales.tsv.gz"
    Check file permissions and disk space
    
  13. Decompression Error

    Error: failed to decompress GZIP file
    File may be corrupted or incomplete
    

Error Response Format

All errors follow the existing pattern:

  • Exit code: non-zero
  • Error message to stderr
  • JSON errors include structured details when available
{
  "error": {
    "code": "REPORT_NOT_AVAILABLE",
    "message": "report not available for date",
    "details": {
      "date": "2024-01-20",
      "frequency": "DAILY",
      "hint": "Reports are typically available the day after the report date"
    }
  }
}

File Handling

GZIP Compression

  1. Sales Reports

    • Always returned as GZIP-compressed TSV files
    • File extension: .tsv.gz
    • Decompressed extension: .tsv
  2. Analytics Reports

    • Typically returned as GZIP-compressed CSV files
    • File extension: .csv.gz
    • Decompressed extension: .csv
  3. Decompression

    • Use Go's compress/gzip package
    • Validate decompressed content before writing
    • Preserve original compressed file unless --decompress is used without custom output path
  4. File Naming

    • Default: {reportType}_{date}_{frequency}.{ext}.gz
    • Sales: sales_report_2024-01-20_SALES.tsv.gz
    • Analytics: analytics_report_{requestId}_{instanceId}.csv.gz
    • Custom paths via --output flag
  5. File Permissions

    • Write files with 0644 permissions (readable by owner and group)
    • Create parent directories if they don't exist

Testing Requirements

Unit Tests

Client Layer (internal/asc/client.go)

  1. GetSalesReport

    • Test query parameter building (all required filters)
    • Test optional version parameter
    • Test binary response handling (GZIP)
    • Test error handling (400, 404, 403)
    • Test date format validation
  2. CreateAnalyticsReportRequest

    • Test request body construction
    • Test required fields validation
    • Test response parsing
    • Test error handling (400, 403, 404)
  3. GetAnalyticsReportRequests

    • Test query parameter building (filter[app], filter[id], filter[state])
    • Test response parsing
    • Test pagination (links.next)
    • Test error handling
  4. GetAnalyticsReports

    • Test query parameter building (filter[analyticsReportRequest], include)
    • Test response parsing with included resources
    • Test pagination
    • Test error handling
  5. GetAnalyticsReportInstances

    • Test query parameter building (filter[analyticsReport], filter[date])
    • Test response parsing
    • Test error handling
  6. GetAnalyticsReportSegments

    • Test query parameter building (filter[analyticsReportInstance])
    • Test response parsing (download URLs)
    • Test error handling
  7. DownloadAnalyticsReport

    • Test download URL retrieval
    • Test binary response handling
    • Test error handling (expired URLs, 404)

CLI Layer (cmd/analytics.go)

  1. AnalyticsSalesCommand

    • Test flag validation (missing required flags)
    • Test vendor number validation
    • Test report type validation
    • Test frequency validation
    • Test date format validation
    • Test file writing
    • Test GZIP decompression
    • Test output formats (json, table, markdown)
  2. AnalyticsRequestCommand

    • Test flag validation (missing --app, --access-type)
    • Test access type validation
    • Test output formats
  3. AnalyticsRequestsCommand

    • Test flag validation
    • Test filter combinations (--request-id, --state)
    • Test pagination (--next)
    • Test output formats
  4. AnalyticsGetCommand

    • Test flag validation (missing --request-id)
    • Test instance filtering (--instance-id, --date)
    • Test --include-segments flag
    • Test output formats
  5. AnalyticsDownloadCommand

    • Test flag validation (missing --request-id, --instance-id)
    • Test segment resolution (single vs multiple)
    • Test file writing
    • Test GZIP decompression
    • Test output formats

Integration Tests (Opt-in)

Environment Variables:

  • ASC_ANALYTICS_VENDOR_NUMBER - Vendor number for sales reports
  • ASC_ANALYTICS_APP_ID - App ID for analytics reports
  • ASC_ANALYTICS_TEST_DATE - Test date for sales reports (default: yesterday)
  • ASC_ANALYTICS_OUTPUT_DIR - Output directory for test files (default: /tmp)

Test Scenarios:

  1. Download daily sales report
  2. Download monthly sales report
  3. Create analytics report request
  4. List analytics report requests
  5. Get analytics reports for a request
  6. Download analytics report file

Skip Conditions:

  • Skip if ASC_ANALYTICS_VENDOR_NUMBER not set (for sales tests)
  • Skip if ASC_ANALYTICS_APP_ID not set (for analytics tests)
  • Skip if API credentials don't have Admin permissions
  • Skip if reports are not yet available (for date-based tests)

Implementation Checklist

Phase 1: Client Methods

  • GetSalesReport(ctx, vendorNumber, reportType, reportSubType, frequency, reportDate, version) - Download sales report
  • CreateAnalyticsReportRequest(ctx, appID, accessType) - Create request
  • GetAnalyticsReportRequests(ctx, appID, opts...) - List requests with filters
  • GetAnalyticsReportRequest(ctx, requestID) - Get specific request
  • GetAnalyticsReports(ctx, requestID, opts...) - Get reports for request
  • GetAnalyticsReportInstances(ctx, reportID, opts...) - Get instances
  • GetAnalyticsReportSegments(ctx, instanceID) - Get segments with download URLs
  • DownloadAnalyticsReport(ctx, downloadURL) - Download report file
  • Add types for request/response structures
  • Add option functions for filters

Phase 2: CLI Commands

  • AnalyticsCommand - Parent command
  • AnalyticsSalesCommand - Download sales reports
  • AnalyticsRequestCommand - Create analytics request
  • AnalyticsRequestsCommand - List requests
  • AnalyticsGetCommand - Get reports
  • AnalyticsDownloadCommand - Download report files
  • Add to RootCommand subcommands list

Phase 3: File Handling

  • GZIP compression/decompression utilities
  • File writing with proper permissions
  • Directory creation for output paths
  • File naming conventions
  • Binary response handling

Phase 4: Validation

  • Vendor number validation
  • Report type validation
  • Frequency validation
  • Date format validation
  • Monthly report date validation
  • Access type validation
  • UUID format validation

Phase 5: Output Formatting

  • Table output for request lists
  • Table output for report metadata
  • Markdown output for all commands
  • JSON output (minified by default)
  • File metadata in JSON output

Phase 6: Error Handling

  • Invalid parameter errors with hints
  • Report availability errors
  • Date validation errors
  • Request state errors
  • Download URL expiration errors
  • File I/O errors

Phase 7: Tests

  • Unit tests for all client methods
  • Unit tests for all CLI commands
  • Integration tests (opt-in)
  • Error case tests
  • File handling tests
  • GZIP compression/decompression tests

API Reference URLs

Official Documentation

  1. Download Sales and Trends Reports

  2. Downloading Analytics Reports

  3. Analytics Reports Overview

  4. Analytics Reports Documentation

  5. Sales and Trends Reports Availability

  6. Sales and Trends Metrics and Dimensions

  7. App Store Connect API Overview

OpenAPI Specification


Design Decisions

  1. Explicit Flags: All commands use long-form flags (--vendor, --type, --frequency) following project conventions

  2. JSON-First: Default output is minified JSON for AI agent consumption (metadata only; binary files written to disk)

  3. Non-Interactive: No prompts; all required information via flags

  4. File Handling: Binary reports written to disk; JSON output contains metadata (file path, size, etc.)

  5. GZIP Handling: Support both compressed and decompressed output via --decompress flag

  6. Vendor Number: Support environment variable (ASC_VENDOR_NUMBER) for convenience

  7. Date Validation: Strict validation with helpful error messages for common mistakes

  8. Multi-Step Workflow: Separate commands for each step of analytics report workflow (request → get → download)

  9. Error Messages: Include actionable hints (e.g., "Reports available day after report date")

  10. File Naming: Descriptive default names with option to customize via --output


Future Enhancements

  1. Report Parsing: Parse TSV/CSV files and output structured JSON

    • asc analytics sales --vendor "..." --parse - Parse and output JSON
  2. Report Aggregation: Combine multiple reports into single output

    • asc analytics sales --vendor "..." --date-range "2024-01-01,2024-01-31"
  3. Automated Downloads: Schedule automatic report downloads

    • asc analytics schedule --vendor "..." --frequency DAILY --output-dir "reports/"
  4. Report Comparison: Compare reports across time periods

    • asc analytics compare --vendor "..." --date1 "2024-01-01" --date2 "2024-02-01"
  5. Analytics Report Types: Support filtering by specific report types

    • asc analytics request --app "..." --report-types APP_USAGE,PERFORMANCE
  6. Report Status Polling: Poll for report completion

    • asc analytics request --app "..." --wait - Poll until ready
  7. Bulk Operations: Download multiple reports in one command

    • asc analytics sales --vendor "..." --dates "2024-01-01,2024-01-02,2024-01-03"

Notes

  • Sales reports are typically available the day after the report date
  • Monthly reports require dates aligned with Apple's reporting periods (typically first day of month)
  • Analytics reports require API key with Admin permissions
  • Analytics data may take 1-2 days to unlock after API credentials are first saved
  • Report download URLs may expire; download promptly after retrieval
  • Sales reports are GZIP-compressed TSV files
  • Analytics reports are typically GZIP-compressed CSV files
  • Vendor number can be found in App Store Connect under "Sales and Trends" → "Reports" → URL parameters
  • Follow existing patterns from BuildsCommand and BetaGroupsCommand for subcommand structure
  • Maintain consistency with existing error handling and output formatting patterns
  • Handle binary file responses appropriately (don't attempt JSON parsing)
  • Consider streaming large files for memory efficiency

Report Type Reference

Sales Report Types

  • SALES - Standard sales reports (downloads, proceeds)
  • PRE_ORDER - Pre-order reports
  • NEWSSTAND - Newsstand reports
  • SUBSCRIPTION - Subscription reports
  • SUBSCRIPTION_EVENT - Subscription event reports

Analytics Report Categories

  • App Store Engagement: Impressions, product page views, custom product pages, in-app events
  • App Store Commerce: Revenue, sales, proceeds
  • App Usage: Active devices, sessions, installations, deletions
  • Framework Usage: Framework and API usage data
  • Performance: Crash rates, hang rates, performance metrics

Note: Implementation should verify available report types against the API documentation, as new types may be added over time.

Originally created by @rudrankriyam on GitHub (Jan 20, 2026). Original GitHub issue: https://github.com/rudrankriyam/App-Store-Connect-CLI/issues/26 # PRD: Analytics and Sales Reports in ASC CLI ## Overview This PRD outlines the implementation of analytics and sales reporting commands for App Store Connect CLI, enabling developers and AI agents to download sales reports, request analytics reports, and retrieve usage metrics programmatically. ## Goals 1. Enable developers to download sales and trends reports via CLI 2. Support requesting and retrieving analytics reports (usage metrics, engagement data) 3. Provide programmatic access to over 50 analytics report types 4. Maintain AI-first design with JSON output by default 5. Follow explicit, non-interactive CLI patterns 6. Handle GZIP-compressed report files appropriately --- ## API Endpoints ### Sales and Trends Reports | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/v1/salesReports` | Download sales and trends reports (returns GZIP file) | **Query Parameters:** - `filter[vendorNumber]` (required) - Vendor number for your developer account - `filter[reportType]` (required) - Report type: `SALES`, `PRE_ORDER`, `NEWSSTAND`, `SUBSCRIPTION`, `SUBSCRIPTION_EVENT` - `filter[reportSubType]` (required) - Report detail level: `SUMMARY`, `DETAILED` - `filter[frequency]` (required) - Time interval: `DAILY`, `WEEKLY`, `MONTHLY`, `YEARLY` - `filter[reportDate]` (required) - Report date in `YYYY-MM-DD` format - `filter[version]` (optional) - Report format version: `1_0` (default), `1_1` **Response:** GZIP-compressed TSV file (binary) ### Analytics Reports (Multi-Step Workflow) | Method | Endpoint | Description | |--------|----------|-------------| | POST | `/v1/analyticsReportRequests` | Create a new analytics report request | | GET | `/v1/analyticsReportRequests` | List analytics report requests | | GET | `/v1/analyticsReportRequests/{id}` | Get specific report request details | | GET | `/v1/analyticsReports` | List analytics reports for a request | | GET | `/v1/analyticsReportInstances` | List report instances (by date/version) | | GET | `/v1/analyticsReportSegments` | Get report segments with download URLs | **Report Categories:** - **App Store Engagement**: Impressions, product page views, custom product pages, in-app events - **App Store Commerce**: Revenue, sales, proceeds - **App Usage**: Active devices, sessions, installations, deletions - **Framework Usage**: Framework and API usage data - **Performance**: Crash rates, hang rates, performance metrics --- ## CLI Commands ### Command Structure ```bash # Sales reports asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20" [flags] # Analytics reports (request) asc analytics request --app "APP_ID" --access-type ONGOING [flags] # Analytics reports (list requests) asc analytics requests --app "APP_ID" [flags] # Analytics reports (get report) asc analytics get --request-id "REQUEST_ID" [flags] # Analytics reports (download) asc analytics download --request-id "REQUEST_ID" --instance-id "INSTANCE_ID" [flags] ``` ### Subcommands #### `sales` - Download Sales and Trends Reports Downloads sales and trends reports as GZIP-compressed TSV files. **Flags:** - `--vendor` (required) - Vendor number (or `ASC_VENDOR_NUMBER` env) - `--type` (required) - Report type: `SALES`, `PRE_ORDER`, `NEWSSTAND`, `SUBSCRIPTION`, `SUBSCRIPTION_EVENT` - `--subtype` (required) - Report subtype: `SUMMARY`, `DETAILED` - `--frequency` (required) - Frequency: `DAILY`, `WEEKLY`, `MONTHLY`, `YEARLY` - `--date` (required) - Report date in `YYYY-MM-DD` format - `--version` (optional) - Report format version: `1_0` (default), `1_1` - `--output` (optional) - Output file path (default: `sales_report_{date}_{type}.tsv.gz`) - `--decompress` (optional) - Automatically decompress GZIP file to `.tsv` - `--output-format` (optional) - Output format for metadata: `json` (default), `table`, `markdown` - `--pretty` (optional) - Pretty-print JSON output **Examples:** ```bash # Download daily sales summary asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20" # Download monthly subscription report asc analytics sales --vendor "12345678" --type SUBSCRIPTION --subtype DETAILED --frequency MONTHLY --date "2024-01-01" # Download and decompress automatically asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20" --decompress # Custom output path asc analytics sales --vendor "12345678" --type SALES --subtype SUMMARY --frequency DAILY --date "2024-01-20" --output "reports/daily_sales.tsv.gz" ``` **JSON Output (metadata):** ```json {"vendorNumber":"12345678","reportType":"SALES","reportSubType":"SUMMARY","frequency":"DAILY","reportDate":"2024-01-20","version":"1_0","filePath":"sales_report_2024-01-20_SALES.tsv.gz","fileSize":12345,"decompressed":false} ``` **Note:** Reports are typically available the day after the report date. Monthly reports require dates aligned with Apple's reporting periods. #### `request` - Create Analytics Report Request Creates a new analytics report request for an app. **Flags:** - `--app` (required) - App Store Connect app ID (or `ASC_APP_ID` env) - `--access-type` (required) - Access type: `ONGOING` (daily updates), `ONE_TIME_SNAPSHOT` (single snapshot) - `--output` (optional) - Output format: `json` (default), `table`, `markdown` - `--pretty` (optional) - Pretty-print JSON output **Examples:** ```bash # Create ongoing analytics report request asc analytics request --app "123456789" --access-type ONGOING # Create one-time snapshot asc analytics request --app "123456789" --access-type ONE_TIME_SNAPSHOT ``` **JSON Output:** ```json {"requestId":"abc123def456","appId":"123456789","accessType":"ONGOING","createdDate":"2024-01-20T12:00:00Z","state":"PROCESSING"} ``` **Note:** Requires API key with **Admin** permissions. Analytics data may take 1-2 days to unlock after API credentials are first saved. #### `requests` - List Analytics Report Requests Lists analytics report requests for an app. **Flags:** - `--app` (required) - App Store Connect app ID (or `ASC_APP_ID` env) - `--request-id` (optional) - Filter by specific request ID - `--state` (optional) - Filter by state: `PROCESSING`, `COMPLETED`, `FAILED` - `--limit` (optional) - Maximum results per page (1-200) - `--next` (optional) - Fetch next page using `links.next` URL - `--output` (optional) - Output format: `json` (default), `table`, `markdown` - `--pretty` (optional) - Pretty-print JSON output **Examples:** ```bash # List all requests for an app asc analytics requests --app "123456789" # Get specific request details asc analytics requests --app "123456789" --request-id "abc123def456" # Filter by state asc analytics requests --app "123456789" --state COMPLETED ``` **JSON Output:** ```json {"data":[{"id":"abc123def456","type":"analyticsReportRequests","attributes":{"accessType":"ONGOING","state":"COMPLETED","createdDate":"2024-01-20T12:00:00Z"},"relationships":{"app":{"data":{"type":"apps","id":"123456789"}}}}],"links":{"self":"...","next":null}} ``` #### `get` - Get Analytics Reports Retrieves analytics reports for a request, including instances and segments. **Flags:** - `--request-id` (required) - Analytics report request ID - `--instance-id` (optional) - Filter by specific instance ID - `--date` (optional) - Filter instances by date (`YYYY-MM-DD`) - `--include-segments` (optional) - Include report segments with download URLs - `--limit` (optional) - Maximum results per page (1-200) - `--next` (optional) - Fetch next page using `links.next` URL - `--output` (optional) - Output format: `json` (default), `table`, `markdown` - `--pretty` (optional) - Pretty-print JSON output **Examples:** ```bash # Get all reports for a request asc analytics get --request-id "abc123def456" # Get reports with segments (download URLs) asc analytics get --request-id "abc123def456" --include-segments # Get specific instance asc analytics get --request-id "abc123def456" --instance-id "instance-123" # Filter by date asc analytics get --request-id "abc123def456" --date "2024-01-20" ``` **JSON Output:** ```json {"data":[{"id":"report-123","type":"analyticsReports","attributes":{"reportType":"APP_USAGE","granularity":"DAILY"},"relationships":{"request":{"data":{"type":"analyticsReportRequests","id":"abc123def456"}},"instances":{"data":[{"type":"analyticsReportInstances","id":"instance-123"}]}},"instances":[{"id":"instance-123","date":"2024-01-20","segments":[{"id":"segment-456","downloadUrl":"https://..."}]}]}],"links":{"self":"...","next":null}} ``` #### `download` - Download Analytics Report Downloads an analytics report file from a segment. **Flags:** - `--request-id` (required) - Analytics report request ID - `--instance-id` (required) - Report instance ID - `--segment-id` (optional) - Specific segment ID (if multiple segments exist) - `--output` (optional) - Output file path (default: `analytics_report_{requestId}_{instanceId}.csv.gz`) - `--decompress` (optional) - Automatically decompress GZIP file to `.csv` - `--output-format` (optional) - Output format for metadata: `json` (default), `table`, `markdown` - `--pretty` (optional) - Pretty-print JSON output **Examples:** ```bash # Download report from instance asc analytics download --request-id "abc123def456" --instance-id "instance-123" # Download and decompress asc analytics download --request-id "abc123def456" --instance-id "instance-123" --decompress # Download specific segment asc analytics download --request-id "abc123def456" --instance-id "instance-123" --segment-id "segment-456" # Custom output path asc analytics download --request-id "abc123def456" --instance-id "instance-123" --output "reports/usage_2024-01-20.csv.gz" ``` **JSON Output (metadata):** ```json {"requestId":"abc123def456","instanceId":"instance-123","segmentId":"segment-456","filePath":"analytics_report_abc123def456_instance-123.csv.gz","fileSize":67890,"decompressed":false,"downloadUrl":"https://..."} ``` **Note:** Report files are typically GZIP-compressed CSV files. Download URLs may expire; download promptly after retrieval. --- ## Request/Response Shapes ### Sales Reports (GET) **Request:** ``` GET /v1/salesReports?filter[vendorNumber]=12345678&filter[reportType]=SALES&filter[reportSubType]=SUMMARY&filter[frequency]=DAILY&filter[reportDate]=2024-01-20&filter[version]=1_0 ``` **Response:** - Content-Type: `application/a-gzip` or `application/gzip` - Body: Binary GZIP-compressed TSV file - Headers may include `Content-Disposition` with filename ### Create Analytics Report Request (POST) **Request:** ```json { "data": { "type": "analyticsReportRequests", "attributes": { "accessType": "ONGOING" }, "relationships": { "app": { "data": { "type": "apps", "id": "123456789" } } } } } ``` **Response:** ```json { "data": { "type": "analyticsReportRequests", "id": "abc123def456", "attributes": { "accessType": "ONGOING", "state": "PROCESSING", "createdDate": "2024-01-20T12:00:00Z" }, "relationships": { "app": { "data": { "type": "apps", "id": "123456789" } } } }, "links": { "self": "https://api.appstoreconnect.apple.com/v1/analyticsReportRequests/abc123def456" } } ``` ### Get Analytics Reports (GET) **Request:** ``` GET /v1/analyticsReports?filter[analyticsReportRequest]=abc123def456&include=instances,instances.segments ``` **Response:** ```json { "data": [ { "type": "analyticsReports", "id": "report-123", "attributes": { "reportType": "APP_USAGE", "granularity": "DAILY" }, "relationships": { "request": { "data": { "type": "analyticsReportRequests", "id": "abc123def456" } }, "instances": { "data": [ { "type": "analyticsReportInstances", "id": "instance-123" } ] } } } ], "included": [ { "type": "analyticsReportInstances", "id": "instance-123", "attributes": { "date": "2024-01-20" }, "relationships": { "segments": { "data": [ { "type": "analyticsReportSegments", "id": "segment-456" } ] } } }, { "type": "analyticsReportSegments", "id": "segment-456", "attributes": { "downloadUrl": "https://analytics.appstoreconnect.apple.com/..." } } ], "links": { "self": "https://api.appstoreconnect.apple.com/v1/analyticsReports?filter[analyticsReportRequest]=abc123def456" } } ``` --- ## Required Fields ### Sales Reports **Required Query Parameters:** - `filter[vendorNumber]`: String - Vendor number (8+ digits) - `filter[reportType]`: Enum - `SALES`, `PRE_ORDER`, `NEWSSTAND`, `SUBSCRIPTION`, `SUBSCRIPTION_EVENT` - `filter[reportSubType]`: Enum - `SUMMARY`, `DETAILED` - `filter[frequency]`: Enum - `DAILY`, `WEEKLY`, `MONTHLY`, `YEARLY` - `filter[reportDate]`: String - Date in `YYYY-MM-DD` format **Optional Query Parameters:** - `filter[version]`: String - Report format version: `1_0` (default), `1_1` ### Analytics Report Requests **Required Fields:** - `type`: `"analyticsReportRequests"` - `attributes.accessType`: Enum - `ONGOING`, `ONE_TIME_SNAPSHOT` - `relationships.app.data.type`: `"apps"` - `relationships.app.data.id`: String - App ID (UUID) --- ## Validation ### Input Validation 1. **Vendor Number** - Required for `sales` command - Must be numeric string (8+ digits) - Can be provided via `--vendor` flag or `ASC_VENDOR_NUMBER` environment variable 2. **Report Type** - Required for `sales` command - Valid values: `SALES`, `PRE_ORDER`, `NEWSSTAND`, `SUBSCRIPTION`, `SUBSCRIPTION_EVENT` - Case-insensitive (normalize to uppercase) 3. **Report Subtype** - Required for `sales` command - Valid values: `SUMMARY`, `DETAILED` - Case-insensitive (normalize to uppercase) 4. **Frequency** - Required for `sales` command - Valid values: `DAILY`, `WEEKLY`, `MONTHLY`, `YEARLY` - Case-insensitive (normalize to uppercase) 5. **Report Date** - Required for `sales` command - Format: `YYYY-MM-DD` (ISO 8601 date) - Must be valid date - For monthly reports, must align with Apple's reporting periods (typically first day of month) 6. **Version** - Optional for `sales` command - Valid values: `1_0` (default), `1_1` - Format: `{major}_{minor}` 7. **App ID** - Required for `request` and `requests` commands - Must be valid UUID format - Can be provided via `--app` flag or `ASC_APP_ID` environment variable 8. **Access Type** - Required for `request` command - Valid values: `ONGOING`, `ONE_TIME_SNAPSHOT` - Case-insensitive (normalize to uppercase) 9. **Request ID** - Required for `get` and `download` commands - Must be valid UUID format 10. **Instance ID** - Required for `download` command - Must be valid UUID format 11. **Segment ID** - Optional for `download` command - Must be valid UUID format - If not provided and multiple segments exist, download first segment 12. **Limit** - Must be between 1 and 200 if provided - Default: API default (typically 50) ### Date Validation 1. **Report Date Format** - Must match `YYYY-MM-DD` format - Validate using Go's `time.Parse("2006-01-02", date)` 2. **Monthly Report Dates** - Monthly reports typically require dates on the first day of the month - Validate and warn if date is not first of month for monthly frequency 3. **Future Dates** - Sales reports are typically available the day after the report date - Warn if requesting future dates or dates too far in the past --- ## Error Handling ### Common Errors 1. **Invalid Vendor Number** ``` Error: invalid vendor number "INVALID" Vendor number must be numeric and 8+ digits ``` 2. **Invalid Report Type** ``` Error: invalid report type "INVALID" Valid types: SALES, PRE_ORDER, NEWSSTAND, SUBSCRIPTION, SUBSCRIPTION_EVENT ``` 3. **Invalid Frequency** ``` Error: invalid frequency "INVALID" Valid frequencies: DAILY, WEEKLY, MONTHLY, YEARLY ``` 4. **Invalid Date Format** ``` Error: invalid date format "2024/01/20" Date must be in YYYY-MM-DD format ``` 5. **Report Not Available** ``` Error: report not available for date "2024-01-20" Reports are typically available the day after the report date ``` 6. **Monthly Report Date Mismatch** ``` Error: monthly reports require dates on the first day of the month Provided: 2024-01-15, Expected: 2024-01-01 ``` 7. **Request Not Found** ``` Error: analytics report request not found for ID "abc123def456" ``` 8. **Report Not Ready** ``` Error: analytics report request is still processing Request ID: abc123def456, State: PROCESSING Wait for state to become COMPLETED before downloading ``` 9. **Download URL Expired** ``` Error: download URL has expired Request a new report instance to get a fresh download URL ``` 10. **Unauthorized** ``` Error: unauthorized. Check your API credentials. Analytics reports require Admin permissions ``` 11. **Rate Limiting** ``` Error: rate limit exceeded. Please try again later. ``` 12. **File Write Error** ``` Error: failed to write report file to "reports/sales.tsv.gz" Check file permissions and disk space ``` 13. **Decompression Error** ``` Error: failed to decompress GZIP file File may be corrupted or incomplete ``` ### Error Response Format All errors follow the existing pattern: - Exit code: non-zero - Error message to stderr - JSON errors include structured details when available ```json { "error": { "code": "REPORT_NOT_AVAILABLE", "message": "report not available for date", "details": { "date": "2024-01-20", "frequency": "DAILY", "hint": "Reports are typically available the day after the report date" } } } ``` --- ## File Handling ### GZIP Compression 1. **Sales Reports** - Always returned as GZIP-compressed TSV files - File extension: `.tsv.gz` - Decompressed extension: `.tsv` 2. **Analytics Reports** - Typically returned as GZIP-compressed CSV files - File extension: `.csv.gz` - Decompressed extension: `.csv` 3. **Decompression** - Use Go's `compress/gzip` package - Validate decompressed content before writing - Preserve original compressed file unless `--decompress` is used without custom output path 4. **File Naming** - Default: `{reportType}_{date}_{frequency}.{ext}.gz` - Sales: `sales_report_2024-01-20_SALES.tsv.gz` - Analytics: `analytics_report_{requestId}_{instanceId}.csv.gz` - Custom paths via `--output` flag 5. **File Permissions** - Write files with `0644` permissions (readable by owner and group) - Create parent directories if they don't exist --- ## Testing Requirements ### Unit Tests #### Client Layer (`internal/asc/client.go`) 1. **GetSalesReport** - Test query parameter building (all required filters) - Test optional `version` parameter - Test binary response handling (GZIP) - Test error handling (400, 404, 403) - Test date format validation 2. **CreateAnalyticsReportRequest** - Test request body construction - Test required fields validation - Test response parsing - Test error handling (400, 403, 404) 3. **GetAnalyticsReportRequests** - Test query parameter building (`filter[app]`, `filter[id]`, `filter[state]`) - Test response parsing - Test pagination (`links.next`) - Test error handling 4. **GetAnalyticsReports** - Test query parameter building (`filter[analyticsReportRequest]`, `include`) - Test response parsing with included resources - Test pagination - Test error handling 5. **GetAnalyticsReportInstances** - Test query parameter building (`filter[analyticsReport]`, `filter[date]`) - Test response parsing - Test error handling 6. **GetAnalyticsReportSegments** - Test query parameter building (`filter[analyticsReportInstance]`) - Test response parsing (download URLs) - Test error handling 7. **DownloadAnalyticsReport** - Test download URL retrieval - Test binary response handling - Test error handling (expired URLs, 404) #### CLI Layer (`cmd/analytics.go`) 1. **AnalyticsSalesCommand** - Test flag validation (missing required flags) - Test vendor number validation - Test report type validation - Test frequency validation - Test date format validation - Test file writing - Test GZIP decompression - Test output formats (json, table, markdown) 2. **AnalyticsRequestCommand** - Test flag validation (missing `--app`, `--access-type`) - Test access type validation - Test output formats 3. **AnalyticsRequestsCommand** - Test flag validation - Test filter combinations (`--request-id`, `--state`) - Test pagination (`--next`) - Test output formats 4. **AnalyticsGetCommand** - Test flag validation (missing `--request-id`) - Test instance filtering (`--instance-id`, `--date`) - Test `--include-segments` flag - Test output formats 5. **AnalyticsDownloadCommand** - Test flag validation (missing `--request-id`, `--instance-id`) - Test segment resolution (single vs multiple) - Test file writing - Test GZIP decompression - Test output formats ### Integration Tests (Opt-in) **Environment Variables:** - `ASC_ANALYTICS_VENDOR_NUMBER` - Vendor number for sales reports - `ASC_ANALYTICS_APP_ID` - App ID for analytics reports - `ASC_ANALYTICS_TEST_DATE` - Test date for sales reports (default: yesterday) - `ASC_ANALYTICS_OUTPUT_DIR` - Output directory for test files (default: `/tmp`) **Test Scenarios:** 1. Download daily sales report 2. Download monthly sales report 3. Create analytics report request 4. List analytics report requests 5. Get analytics reports for a request 6. Download analytics report file **Skip Conditions:** - Skip if `ASC_ANALYTICS_VENDOR_NUMBER` not set (for sales tests) - Skip if `ASC_ANALYTICS_APP_ID` not set (for analytics tests) - Skip if API credentials don't have Admin permissions - Skip if reports are not yet available (for date-based tests) --- ## Implementation Checklist ### Phase 1: Client Methods - [ ] `GetSalesReport(ctx, vendorNumber, reportType, reportSubType, frequency, reportDate, version)` - Download sales report - [ ] `CreateAnalyticsReportRequest(ctx, appID, accessType)` - Create request - [ ] `GetAnalyticsReportRequests(ctx, appID, opts...)` - List requests with filters - [ ] `GetAnalyticsReportRequest(ctx, requestID)` - Get specific request - [ ] `GetAnalyticsReports(ctx, requestID, opts...)` - Get reports for request - [ ] `GetAnalyticsReportInstances(ctx, reportID, opts...)` - Get instances - [ ] `GetAnalyticsReportSegments(ctx, instanceID)` - Get segments with download URLs - [ ] `DownloadAnalyticsReport(ctx, downloadURL)` - Download report file - [ ] Add types for request/response structures - [ ] Add option functions for filters ### Phase 2: CLI Commands - [ ] `AnalyticsCommand` - Parent command - [ ] `AnalyticsSalesCommand` - Download sales reports - [ ] `AnalyticsRequestCommand` - Create analytics request - [ ] `AnalyticsRequestsCommand` - List requests - [ ] `AnalyticsGetCommand` - Get reports - [ ] `AnalyticsDownloadCommand` - Download report files - [ ] Add to `RootCommand` subcommands list ### Phase 3: File Handling - [ ] GZIP compression/decompression utilities - [ ] File writing with proper permissions - [ ] Directory creation for output paths - [ ] File naming conventions - [ ] Binary response handling ### Phase 4: Validation - [ ] Vendor number validation - [ ] Report type validation - [ ] Frequency validation - [ ] Date format validation - [ ] Monthly report date validation - [ ] Access type validation - [ ] UUID format validation ### Phase 5: Output Formatting - [ ] Table output for request lists - [ ] Table output for report metadata - [ ] Markdown output for all commands - [ ] JSON output (minified by default) - [ ] File metadata in JSON output ### Phase 6: Error Handling - [ ] Invalid parameter errors with hints - [ ] Report availability errors - [ ] Date validation errors - [ ] Request state errors - [ ] Download URL expiration errors - [ ] File I/O errors ### Phase 7: Tests - [ ] Unit tests for all client methods - [ ] Unit tests for all CLI commands - [ ] Integration tests (opt-in) - [ ] Error case tests - [ ] File handling tests - [ ] GZIP compression/decompression tests --- ## API Reference URLs ### Official Documentation 1. **Download Sales and Trends Reports** - https://developer.apple.com/documentation/appstoreconnectapi/get-v1-salesreports 2. **Downloading Analytics Reports** - https://developer.apple.com/documentation/AppStoreConnectAPI/downloading-analytics-reports 3. **Analytics Reports Overview** - https://developer.apple.com/documentation/appstoreconnectapi/analytics 4. **Analytics Reports Documentation** - https://developer.apple.com/documentation/analytics-reports 5. **Sales and Trends Reports Availability** - https://developer.apple.com/help/app-store-connect/reference/sales-and-trends-reports-availability/ 6. **Sales and Trends Metrics and Dimensions** - https://developer.apple.com/help/app-store-connect/reference/reporting/sales-and-trends-metrics-and-dimensions/ 7. **App Store Connect API Overview** - https://developer.apple.com/documentation/appstoreconnectapi ### OpenAPI Specification - **Official Spec Download**: https://developer.apple.com/news/releases/ - **OpenAPI Mirror**: https://github.com/EvanBacon/App-Store-Connect-OpenAPI-Spec ### Related Documentation - **App Store Connect API Release Notes**: https://developer.apple.com/documentation/appstoreconnectapi/app-store-connect-api-release-notes - **Overview of Reporting Tools**: https://developers.apple.com/help/app-store-connect/measure-app-performance/overview-of-reporting-tools - **Download App Analytics Reports**: https://developer.apple.com/help/app-store-connect/view-app-analytics/download-app-analytics-reports/ --- ## Design Decisions 1. **Explicit Flags**: All commands use long-form flags (`--vendor`, `--type`, `--frequency`) following project conventions 2. **JSON-First**: Default output is minified JSON for AI agent consumption (metadata only; binary files written to disk) 3. **Non-Interactive**: No prompts; all required information via flags 4. **File Handling**: Binary reports written to disk; JSON output contains metadata (file path, size, etc.) 5. **GZIP Handling**: Support both compressed and decompressed output via `--decompress` flag 6. **Vendor Number**: Support environment variable (`ASC_VENDOR_NUMBER`) for convenience 7. **Date Validation**: Strict validation with helpful error messages for common mistakes 8. **Multi-Step Workflow**: Separate commands for each step of analytics report workflow (request → get → download) 9. **Error Messages**: Include actionable hints (e.g., "Reports available day after report date") 10. **File Naming**: Descriptive default names with option to customize via `--output` --- ## Future Enhancements 1. **Report Parsing**: Parse TSV/CSV files and output structured JSON - `asc analytics sales --vendor "..." --parse` - Parse and output JSON 2. **Report Aggregation**: Combine multiple reports into single output - `asc analytics sales --vendor "..." --date-range "2024-01-01,2024-01-31"` 3. **Automated Downloads**: Schedule automatic report downloads - `asc analytics schedule --vendor "..." --frequency DAILY --output-dir "reports/"` 4. **Report Comparison**: Compare reports across time periods - `asc analytics compare --vendor "..." --date1 "2024-01-01" --date2 "2024-02-01"` 5. **Analytics Report Types**: Support filtering by specific report types - `asc analytics request --app "..." --report-types APP_USAGE,PERFORMANCE` 6. **Report Status Polling**: Poll for report completion - `asc analytics request --app "..." --wait` - Poll until ready 7. **Bulk Operations**: Download multiple reports in one command - `asc analytics sales --vendor "..." --dates "2024-01-01,2024-01-02,2024-01-03"` --- ## Notes - Sales reports are typically available the day after the report date - Monthly reports require dates aligned with Apple's reporting periods (typically first day of month) - Analytics reports require API key with **Admin** permissions - Analytics data may take 1-2 days to unlock after API credentials are first saved - Report download URLs may expire; download promptly after retrieval - Sales reports are GZIP-compressed TSV files - Analytics reports are typically GZIP-compressed CSV files - Vendor number can be found in App Store Connect under "Sales and Trends" → "Reports" → URL parameters - Follow existing patterns from `BuildsCommand` and `BetaGroupsCommand` for subcommand structure - Maintain consistency with existing error handling and output formatting patterns - Handle binary file responses appropriately (don't attempt JSON parsing) - Consider streaming large files for memory efficiency --- ## Report Type Reference ### Sales Report Types - `SALES` - Standard sales reports (downloads, proceeds) - `PRE_ORDER` - Pre-order reports - `NEWSSTAND` - Newsstand reports - `SUBSCRIPTION` - Subscription reports - `SUBSCRIPTION_EVENT` - Subscription event reports ### Analytics Report Categories - **App Store Engagement**: Impressions, product page views, custom product pages, in-app events - **App Store Commerce**: Revenue, sales, proceeds - **App Usage**: Active devices, sessions, installations, deletions - **Framework Usage**: Framework and API usage data - **Performance**: Crash rates, hang rates, performance metrics **Note:** Implementation should verify available report types against the API documentation, as new types may be added over time.
kerem closed this issue 2026-02-26 21:32:43 +03:00
Author
Owner

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

Implemented in PR #32 and released in 0.2.0. Closing as complete.

<!-- gh-comment-id:3776661743 --> @rudrankriyam commented on GitHub (Jan 21, 2026): Implemented in PR #32 and released in 0.2.0. Closing as complete.
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#4
No description provided.