> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beatpass.ca/llms.txt
> Use this file to discover all available pages before exploring further.

# Commerce & Licensing API

> Track purchases, license certificates, exclusive license presets, and safe producer finance references.

## Overview

The Commerce & Licensing API handles the complete purchase lifecycle - from pricing calculation through card payment to license certificate generation. It also covers exclusive license preset management and safe producer finance references for approved integrations.

<Info>
  **Base URL:** `https://open.beatpass.ca/api/v1`

  **Authentication:** All endpoints require a valid Bearer token unless noted otherwise.
</Info>

***

## Track Purchases

### Calculate Price

Get pricing details for a track before initiating purchase.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/tracks/{track}/purchase/calculate-price
```

<ParamField path="track" type="integer" required>
  Track ID to get pricing for.
</ParamField>

**Response:**

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "status": "success",
  "data": {
    "base_price": 29.99,
    "platform_fee": 4.50,
    "total_amount": 29.99,
    "currency": "USD",
    "is_exclusive": true
  }
}
```

***

### Initiate Purchase

Start the purchase flow by creating a Stripe <Tooltip tip="A Stripe object that tracks a payment from creation to completion. The client_secret is used to confirm payment on the frontend.">PaymentIntent</Tooltip>.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/tracks/{track}/purchase/initiate
```

<ParamField path="track" type="integer" required>
  Track ID to purchase.
</ParamField>

**Response:**

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "status": "success",
  "data": {
    "client_secret": "pi_xxx_secret_xxx",
    "purchase_id": 42,
    "pricing": {
      "base_price": 29.99,
      "platform_fee": 4.50,
      "total_amount": 29.99,
      "currency": "USD"
    }
  }
}
```

<Warning>
  Use the `client_secret` with Stripe.js on the frontend to complete payment confirmation. Do not store or log client secrets.
</Warning>

**Common Errors:**

| Error                          | Code | Cause                      |
| ------------------------------ | ---- | -------------------------- |
| Track purchases not enabled    | 403  | Feature disabled in config |
| Cannot purchase own track      | 422  | Buyer is the track artist  |
| Already purchased              | 422  | User already owns license  |
| Artist not set up for payments | 422  | Artist is not payout-ready |

***

### Check Purchase Status

Check whether the authenticated user has purchased a specific track.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/tracks/{track}/purchase/status
```

**Response:**

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "status": "success",
  "data": {
    "has_purchased": true,
    "can_purchase": false,
    "reason": "already_purchased"
  }
}
```

***

### User Purchases

Get the authenticated user's purchase history.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/purchases
```

<ParamField query="per_page" type="integer">
  Results per page. Default: `15`.
</ParamField>

***

### Artist Sales

Get sales data for the authenticated artist, including payout and balance summary fields when available.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/artist/sales
```

**Response:**

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "status": "success",
  "data": {
    "earnings": {
      "total_sales": 12,
      "total_revenue": 245.50,
      "total_revenue_formatted": "\$245.50 USD",
      "pending_payout": 89.00,
      "paid_out": 156.50,
      "currency": "USD"
    },
    "recent_purchases": [
      {
        "id": 1,
        "track_id": 42,
        "track_name": "Summer Vibes",
        "artist_amount": 25.49,
        "total_amount": 29.99,
        "platform_fee": 4.50,
        "status": "succeeded",
        "purchased_at": "2025-01-15 14:30:00"
      }
    ]
  }
}
```

***

## Purchase Flow

<Steps>
  <Step title="Calculate Price">
    Call `POST /tracks/{track}/purchase/calculate-price` to get current pricing.
  </Step>

  <Step title="Initiate Purchase">
    Call `POST /tracks/{track}/purchase/initiate` to create a Stripe PaymentIntent.
  </Step>

  <Step title="Confirm Payment">
    Use the returned `client_secret` with Stripe.js `confirmCardPayment()` on the frontend.
  </Step>

  <Step title="Webhook Confirmation">
    Stripe sends a `payment_intent.succeeded` webhook to BeatPass. The platform activates the license and generates a certificate.
  </Step>

  <Step title="Access License">
    The buyer can download the track and retrieve their license certificate.
  </Step>
</Steps>

```mermaid theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
sequenceDiagram
    participant Client
    participant API as BeatPass API
    participant Stripe

    Client->>API: POST /tracks/{id}/purchase/calculate-price
    API-->>Client: Pricing breakdown
    Client->>API: POST /tracks/{id}/purchase/initiate
    API->>Stripe: Create PaymentIntent
    Stripe-->>API: client_secret
    API-->>Client: client_secret
    Client->>Stripe: confirmCardPayment(client_secret)
    Stripe-->>Client: Payment confirmed
    Stripe->>API: Webhook (payment_intent.succeeded)
    API->>API: Activate license & generate certificate
    Client->>API: GET /tracks/{id}/license
    API-->>Client: License certificate
```

***

## License Certificates

### Generate License

Generate a <Tooltip tip="A verifiable document generated after purchase that proves the buyer's right to use a beat under specific terms.">license certificate</Tooltip> for a purchased track.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/tracks/{track}/generate-license
```

### Check License

Check if a license exists for a track.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/tracks/{track}/check-license
```

### Batch Check Licenses

Check licenses for multiple tracks at once.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/tracks/check-licenses-batch
```

### View License Certificate

Retrieve the license certificate data for a purchased track.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/tracks/{track}/license-certificate
```

<ParamField path="track" type="integer" required>
  Track ID to retrieve the license certificate for.
</ParamField>

### Download License PDF

Download the license certificate as a PDF document.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/tracks/{track}/download-license-pdf
```

### Verify License (Public)

Verify a license certificate by its UUID. This endpoint does not require authentication.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/verify-license/{uuid}
```

<ParamField path="uuid" type="string" required>
  License certificate UUID.
</ParamField>

### Revoke License

Revoke a previously issued license.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/licenses/{uuid}/revoke
```

### User Licenses

Get all license certificates for the authenticated user.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/user/licenses
```

***

## Exclusive License Presets

Manage reusable pricing presets — <Tooltip tip="A saved set of pricing and rights configurations that producers can reuse across multiple beats for exclusive sales.">exclusive license presets</Tooltip> — for exclusive license sales.

### List Presets

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/exclusive-license-presets
```

### Get Default Config

Retrieve the default exclusive license configuration.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/exclusive-license-presets/default-config
```

### Get Preset

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/exclusive-license-presets/{preset}
```

### Create Preset

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/exclusive-license-presets
```

### Update Preset

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
PUT /api/v1/exclusive-license-presets/{preset}
```

### Delete Preset

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
DELETE /api/v1/exclusive-license-presets/{preset}
```

### Set Default Preset

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/exclusive-license-presets/{preset}/set-default
```

***

## Artist Exclusive License Default

Manage the artist's default exclusive license configuration, auto-applied to new tracks.

### Get Default

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/artist/exclusive-license-default
```

### Set Default

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/artist/exclusive-license-default
```

***

## Coupon Validation

Validate a discount code during checkout. This is the only user-facing coupon endpoint — coupon creation and management require administrative access.

### Validate Coupon Code

Check if a coupon code is valid and calculate the discount amount.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/coupons/validate
```

<ParamField body="code" type="string" required>
  Coupon code to validate.
</ParamField>

<ParamField body="product_id" type="integer">
  Product/plan ID the coupon will be applied to.
</ParamField>

<ParamField body="price_id" type="integer">
  Price ID the coupon will be applied to.
</ParamField>

<ParamField body="amount" type="number">
  Original amount (before discount) for calculating savings.
</ParamField>

**Success Response:**

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "status": "success",
  "coupon": {
    "id": 1,
    "code": "SAVE20",
    "type": "percentage",
    "amount": 20
  },
  "discount_amount": 5.99,
  "final_amount": 23.99,
  "savings": 5.99,
  "valid": true
}
```

**Error Responses:**

| Error                              | Code | Cause                             |
| ---------------------------------- | ---- | --------------------------------- |
| Invalid or expired coupon code     | 422  | Code not found or expired         |
| You cannot use this coupon         | 422  | User-specific restriction         |
| Cannot be applied to selected plan | 422  | Coupon not valid for this product |

***

## Producer Payout Setup

<Info>
  BEATPAY bank payout setup is an in-product Producer Finances workflow, not a public developer integration surface. Do not build integrations against undocumented payout setup routes.
</Info>

### Stripe Connect Status

Check whether the authenticated artist has completed Stripe Connect onboarding when Stripe is the payout setup shown to that artist.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/artist/stripe-connect/status
```

### Stripe Connect Onboarding Link

Generate a Stripe Connect onboarding link for the authenticated artist when Stripe Connect onboarding is available.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
POST /api/v1/artist/stripe-connect/onboard
```

### View Legacy Stripe Finances

Get the artist's legacy Stripe Connect financial overview where available.

```http theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
GET /api/v1/artist/stripe-connect/finances
```

***

## Related Resources

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/developers/webhooks">
    Payment event processing overview for purchase confirmation.
  </Card>

  <Card title="Error Catalog" icon="triangle-exclamation" href="/developers/error-catalog">
    Purchase and licensing error codes.
  </Card>
</CardGroup>
