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

# Release Management Guide

> Create, manage, and distribute music releases with automated product and asset generation

## Overview

The Royalti.io Release Management system streamlines the process of preparing and distributing music releases. This guide covers creating releases, managing tracks and media, submitting for review, and leveraging the auto-creation pipeline that generates Products and Assets automatically upon approval.

## Prerequisites

### Addon Activation

The Releases feature requires an active subscription. Contact your account administrator to enable this addon for your workspace.

### Authentication

<Note>
  All release endpoints require authentication with a Bearer token.
</Note>

```javascript Node.js theme={null}
const token = 'your_jwt_token';
const headers = {
  'Authorization': `Bearer ${token}`,
  'Content-Type': 'application/json'
};
```

## Release Creation Workflow

<Steps>
  <Step title="Create Draft Release">
    Create a new release with required metadata and at least one track.

    ```javascript Node.js theme={null}
    const response = await fetch('https://api.royalti.io/releases', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        title: 'Summer Vibes',
        displayArtist: 'The Wave Collective',
        artists: {
          'Artist Name': 'primary'  // Auto-creates artist if name provided
          // OR use existing artist UUID: '550e8400-e29b-41d4-a716-446655440000': 'primary'
        },
        format: 'Single',           // Single, EP, Album, LP, Video
        type: 'Audio',              // Audio, Video
        version: 'Radio Edit',
        label: 'Independent Records',
        copyright: '2024 The Wave Collective',
        releaseDate: '2024-12-01',
        preReleaseDate: '2024-11-15',
        mainGenre: ['Pop', 'Electronic'],
        subGenre: ['Synth Pop'],
        explicit: null,             // 'explicit', 'clean', or null
        contributors: [
          {
            role: 'Producer',
            name: 'John Mix',
            isni: '0000000123456789'
          },
          {
            role: 'Songwriter',
            name: 'Jane Melody',
            isni: null
          }
        ],
        metadata: {
          upc: '123456789012',
          catalogNumber: 'IND001'
        },
        tracks: [
          {
            title: 'Summer Nights',
            displayArtist: 'The Wave Collective',
            artists: {
              'The Wave Collective': 'primary',
              'Guest Vocalist': 'featuring'
            },
            version: 'Radio Edit',
            isrc: 'USCM51500001',
            iswc: 'T-123.456.789-0',
            duration: 210,
            language: 'en',
            mainGenre: ['Pop'],
            subGenre: ['Synth Pop'],
            explicit: 'clean',
            lyrics: 'Verse 1\nChorus\nVerse 2\nChorus\nBridge\nChorus',
            contributors: {
              songwriter: ['Jane Melody', 'The Wave Collective'],
              producer: ['John Mix']
            },
            metadata: {
              bpm: 120,
              key: 'C Major'
            }
          }
        ]
      })
    });

    const result = await response.json();
    console.log('Release created:', result.data.id);
    ```
  </Step>

  <Step title="Upload Media Files">
    Add artwork, audio files, and supporting documents to your release.

    ```javascript Node.js theme={null}
    // Upload release-level media (artwork, documents)
    const formData = new FormData();
    formData.append('files', artworkBuffer, 'album-cover.jpg');
    formData.append('files', contractBuffer, 'distribution-agreement.pdf');

    const mediaResponse = await fetch(`https://api.royalti.io/releases/${releaseId}/media/files`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`
      },
      body: formData
    });

    // Upload track audio file
    const trackFormData = new FormData();
    trackFormData.append('file', audioBuffer, 'summer-nights.wav');

    const trackMediaResponse = await fetch(
      `https://api.royalti.io/releases/${releaseId}/tracks/${trackId}/media/file`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`
        },
        body: trackFormData
      }
    );
    ```

    <Note>
      Media files are stored in temporary storage until the release is approved. Upon approval, they are automatically transferred to permanent storage.
    </Note>
  </Step>

  <Step title="Submit External Links">
    For large files, submit links from WeTransfer, Google Drive, Dropbox, or other cloud services.

    ```javascript Node.js theme={null}
    const linkResponse = await fetch(`https://api.royalti.io/releases/${releaseId}/media/links`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        links: [
          {
            url: 'https://wetransfer.com/downloads/abc123',
            name: 'High-Quality Masters',
            type: 'audio'
          },
          {
            url: 'https://drive.google.com/file/d/xyz789',
            name: 'Album Artwork 4K',
            type: 'image'
          }
        ]
      })
    });

    // For individual track media links
    const trackLinkResponse = await fetch(
      `https://api.royalti.io/releases/${releaseId}/tracks/${trackId}/media/link`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          url: 'https://www.dropbox.com/s/track123',
          name: 'Summer Nights Master',
          type: 'audio'
        })
      }
    );
    ```

    <Info>
      Supported platforms: WeTransfer, Google Drive, Dropbox, OneDrive, Box, Mega, MediaFire
    </Info>
  </Step>

  <Step title="Submit for Review">
    Once all metadata and media are complete, submit the release for admin review.

    ```javascript Node.js theme={null}
    const submitResponse = await fetch(`https://api.royalti.io/releases/${releaseId}/submit`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`
      }
    });

    const submitResult = await submitResponse.json();
    if (submitResult.success) {
      console.log('Release submitted successfully');
      console.log('Status:', submitResult.data.status); // 'submitted'
    }
    ```

    <Warning>
      Releases must have at least 1 track and 1 primary artist to be submitted. Only releases in 'draft' or 'rejected' status can be submitted.
    </Warning>
  </Step>
</Steps>

## Release Metadata

### Required Fields

* **title**: Release title
* **displayArtist**: How artist name appears on the release
* **artists**: Object mapping artist UUIDs or names to roles ('primary', 'featuring')
* **tracks**: Array of at least one track

### Optional Fields

* **format**: Single (default), EP, Album, LP, Video
* **type**: Audio (default), Video
* **version**: Deluxe Edition, Remastered, etc.
* **label**: Record label name
* **copyright**: Copyright notice
* **releaseDate**: Public release date
* **preReleaseDate**: Early access date
* **mainGenre**: Array of primary genres
* **subGenre**: Array of secondary genres
* **explicit**: 'explicit', 'clean', or null
* **contributors**: Array of contributors with roles and ISNI codes
* **metadata**: Custom fields (UPC, catalog number, etc.)

### Artist Resolution

The system supports flexible artist handling:

```javascript Node.js theme={null}
// Option 1: Use existing artist UUIDs
{
  artists: {
    '550e8400-e29b-41d4-a716-446655440000': 'primary',
    '660e8400-e29b-41d4-a716-446655441111': 'featuring'
  }
}

// Option 2: Use artist names (auto-creates if not found)
{
  artists: {
    'John Doe': 'primary',
    'Jane Smith': 'featuring'
  }
}

// Artist roles
// - primary: Main artist(s) on the release
// - featuring: Featured/guest artist(s)
```

## Track Management

### Creating Tracks

Tracks can be added during release creation or afterward:

```javascript Node.js theme={null}
const trackResponse = await fetch(`https://api.royalti.io/releases/${releaseId}/tracks`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    title: 'Midnight Dreams',
    displayArtist: 'The Wave Collective',
    artists: {
      'The Wave Collective': 'primary'
    },
    version: 'Extended Mix',
    isrc: 'USCM51500002',
    duration: 285,
    language: 'en',
    mainGenre: ['Electronic'],
    explicit: null
  })
});
```

### Linking Existing Assets

Link previously created Assets to a release with optional overrides:

```javascript Node.js theme={null}
const linkResponse = await fetch(
  `https://api.royalti.io/releases/${releaseId}/tracks/link-asset`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      assetId: '770e8400-e29b-41d4-a716-446655442222',
      trackNumber: 2,  // Optional specific position
      overrides: {
        title: 'Midnight Dreams (Radio Edit)',
        version: 'Radio Edit',
        explicit: 'clean',
        duration: 210  // Override for radio edit
      }
    })
  }
);
```

<Info>
  Linking Assets preserves the original Asset data while allowing release-specific customizations through overrides.
</Info>

### Reordering Tracks

```javascript Node.js theme={null}
const reorderResponse = await fetch(
  `https://api.royalti.io/releases/${releaseId}/tracks/reorder`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      trackOrder: [
        'track-3-uuid',
        'track-1-uuid',
        'track-2-uuid'
      ]
    })
  }
);
```

### Updating Tracks

```javascript Node.js theme={null}
const updateResponse = await fetch(
  `https://api.royalti.io/releases/${releaseId}/tracks/${trackId}`,
  {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      title: 'Summer Nights (Updated Mix)',
      duration: 215,
      metadata: {
        bpm: 122,
        key: 'D Major'
      }
    })
  }
);
```

## Media Management

### Storage Architecture

<Note>
  All media is initially stored in temporary storage. Upon release approval, media is automatically transferred to your workspace's permanent storage location.
</Note>

### Release-Level Media

Release-level media supports multiple files (artwork, documents, promotional materials):

```javascript Node.js theme={null}
const formData = new FormData();
formData.append('files', coverArtBuffer, 'cover.jpg');
formData.append('files', backCoverBuffer, 'back-cover.jpg');
formData.append('files', contractBuffer, 'contract.pdf');

const response = await fetch(`https://api.royalti.io/releases/${releaseId}/media/files`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`
  },
  body: formData
});

const result = await response.json();
result.data.forEach(media => {
  console.log(`Uploaded: ${media.name} (${media.type})`);
  console.log(`Temp URL: ${media.cloudUrl}`);
  console.log(`Size: ${media.metadata.fileSize} bytes`);
});
```

### Track-Level Media

Each track supports one audio or video file:

```javascript Node.js theme={null}
const formData = new FormData();
formData.append('file', audioBuffer, 'track.wav');

const response = await fetch(
  `https://api.royalti.io/releases/${releaseId}/tracks/${trackId}/media/file`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`
    },
    body: formData
  }
);
```

<Warning>
  Each track can have only one audio or video file. Uploading a new file replaces the existing one.
</Warning>

### Deleting Media

```javascript Node.js theme={null}
// Delete release media
await fetch(`https://api.royalti.io/releases/${releaseId}/media/${mediaId}`, {
  method: 'DELETE',
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

// Delete track media
await fetch(
  `https://api.royalti.io/releases/${releaseId}/tracks/${trackId}/media/${mediaId}`,
  {
    method: 'DELETE',
    headers: {
      'Authorization': `Bearer ${token}`
    }
  }
);
```

## Review and Approval Process

### Feedback System

Users and admins can provide feedback on releases to facilitate communication during the review process. Feedback can be public (visible to release owner) or internal (admin-only).

#### Standard Feedback

Create feedback from the authenticated user:

```javascript Node.js theme={null}
const feedbackResponse = await fetch(`https://api.royalti.io/releases/${releaseId}/feedback`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    message: 'The track mix sounds great! Consider adding lyrics metadata.',
    isInternal: false  // Visible to release owner
  })
});

const result = await feedbackResponse.json();
if (result.success) {
  console.log('Feedback added:', result.data.id);
  console.log('From user:', result.data.fromUser.firstName);
}
```

#### Admin Internal Feedback

Admins can create internal feedback visible only to other admins:

```javascript Node.js theme={null}
const internalFeedback = await fetch(`https://api.royalti.io/releases/${releaseId}/feedback`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    message: 'ISRC validation required before final approval.',
    isInternal: true  // Only visible to admins
  })
});
```

<Warning>
  Only users with `admin` or `owner` roles can create internal feedback. Regular users will receive a 403 Forbidden error.
</Warning>

#### API Key Feedback (On Behalf Of Users)

When using API keys for automated integrations, you can specify which user the feedback should be attributed to using the `fromUserId` parameter:

```javascript Node.js theme={null}
// Using an API key to create feedback on behalf of a specific user
const apiKeyFeedback = await fetch(`https://api.royalti.io/releases/${releaseId}/feedback`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,  // Workspace API key
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    message: 'Automated quality check passed. All metadata fields validated.',
    isInternal: false,
    fromUserId: '550e8400-e29b-41d4-a716-446655440000'  // Specific user in workspace
  })
});
```

```python Python theme={null}
import requests

# Python example using API key with fromUserId
response = requests.post(
    f'https://api.royalti.io/releases/{release_id}/feedback',
    headers={
        'Authorization': f'Bearer {api_key}',
        'Content-Type': 'application/json'
    },
    json={
        'message': 'Automated quality check passed. All metadata fields validated.',
        'isInternal': False,
        'fromUserId': '550e8400-e29b-41d4-a716-446655440000'
    }
)

if response.ok:
    data = response.json()
    print(f"Feedback created: {data['data']['id']}")
```

<Info>
  If `fromUserId` is not provided, feedback is attributed to the authenticated user (or workspace admin for API keys).
</Info>

#### Validation Rules for fromUserId

When specifying a `fromUserId`, the API validates:

1. **User Exists**: The user must exist in the same workspace
2. **User Active**: The user account must be active (not suspended)
3. **Release Access**: The user must have access to the release:
   * User is the release owner, OR
   * User has `admin` or `owner` role

**Error Examples:**

```javascript Node.js theme={null}
// User not found in workspace
{
  "success": false,
  "message": "Specified user not found in this workspace"
}

// User inactive
{
  "success": false,
  "message": "Specified user is not active"
}

// User lacks release access
{
  "success": false,
  "message": "Specified user does not have access to this release"
}
```

#### Best Practices

**When to Use fromUserId:**

* **Automated Systems**: Quality check tools providing feedback as specific QA users
* **Third-Party Integrations**: External platforms creating feedback on behalf of workspace members
* **Workflow Automation**: Release management systems attributing feedback to relevant team members

**When NOT to Use fromUserId:**

* **Direct User Actions**: When the actual authenticated user is providing feedback
* **Anonymous Feedback**: System-level feedback that shouldn't be attributed to a specific user

**Example Use Case:**

```javascript Node.js theme={null}
// Automated mastering service providing feedback as the audio engineer
async function submitMasteringFeedback(releaseId, engineerId, feedback) {
  try {
    const response = await fetch(`https://api.royalti.io/releases/${releaseId}/feedback`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${MASTERING_SERVICE_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        message: feedback,
        isInternal: false,
        fromUserId: engineerId  // Attribute to the assigned audio engineer
      })
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`Failed to submit feedback: ${error.message}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Mastering feedback failed:', error);
    throw error;
  }
}

// Usage
await submitMasteringFeedback(
  releaseId,
  'engineer-user-id',
  'Mastering complete. Final mix approved for distribution.'
);
```

### Admin Review (Admin Only)

Admins can approve or reject submitted releases:

```javascript Node.js theme={null}
// Approve release
const approveResponse = await fetch(`https://api.royalti.io/releases/${releaseId}/review`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    action: 'approve',
    feedback: 'All metadata verified. Approved for distribution.'
  })
});

// Reject release with feedback
const rejectResponse = await fetch(`https://api.royalti.io/releases/${releaseId}/review`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    action: 'reject',
    feedback: 'Missing ISRC codes for tracks 2 and 3. Please update and resubmit.'
  })
});
```

<Info>
  Only releases with status 'submitted' can be reviewed. Approved releases automatically trigger the auto-creation pipeline.
</Info>

## Auto-Creation Pipeline

When a release is approved, an automated pipeline generates Product and Asset records:

### Pipeline Stages

```
Approved → Auto-creation: pending → Product/Asset Generation →
Media Transfer → Auto-creation: success → Status: completed
```

### Monitoring Auto-Creation

```javascript Node.js theme={null}
const releaseResponse = await fetch(`https://api.royalti.io/releases/${releaseId}`, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

const release = await releaseResponse.json();
console.log('Status:', release.data.status);                    // 'approved' or 'completed'
console.log('Auto-creation:', release.data.autoCreationStatus); // 'pending', 'success', 'failed'

if (release.data.autoCreationStatus === 'success') {
  console.log('Product created:', release.data.productId);
  console.log('Assets created:', release.data.assetIds);
}
```

### Auto-Creation Status Values

* **null**: Auto-creation not started (draft, submitted, under\_review, rejected)
* **pending**: Pipeline in progress
* **success**: Product and Assets successfully created
* **failed**: Pipeline encountered errors

### Error Handling

If auto-creation fails, admins can investigate and revert:

```javascript Node.js theme={null}
// Revert failed release for re-review (Admin only)
const revertResponse = await fetch(
  `https://api.royalti.io/releases/${releaseId}/revert-status`,
  {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      targetStatus: 'submitted',
      reason: 'Auto-creation failed due to missing artist metadata. Reverting for corrections.'
    })
  }
);
```

<Note>
  Status reversion creates a complete audit trail and clears auto-creation artifacts.
</Note>

## Querying and Filtering Releases

### List All Releases

```javascript Node.js theme={null}
const response = await fetch('https://api.royalti.io/releases?page=1&limit=20', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

const result = await response.json();
console.log('Total releases:', result.pagination.total);
console.log('Releases:', result.data.releases);
console.log('Statistics:', result.stats);
```

### Filter by Status

```javascript Node.js theme={null}
const draftReleases = await fetch(
  'https://api.royalti.io/releases?status=draft&limit=50',
  {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  }
);

// Available statuses: draft, submitted, under_review, approved, rejected, completed
```

### Filter by Format and Type

```javascript Node.js theme={null}
const albums = await fetch(
  'https://api.royalti.io/releases?format=Album&type=Audio',
  {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  }
);
```

### Search Releases

```javascript Node.js theme={null}
const searchResults = await fetch(
  'https://api.royalti.io/releases?search=Summer',
  {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  }
);

// Searches title, displayArtist, and description fields
```

### Release Statistics

```javascript Node.js theme={null}
const statsResponse = await fetch('https://api.royalti.io/releases/stats', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

const stats = await statsResponse.json();
console.log('Draft:', stats.data.draft);
console.log('Submitted:', stats.data.submitted);
console.log('Approved:', stats.data.approved);
console.log('Completed:', stats.data.completed);
console.log('Rejected:', stats.data.rejected);
```

## Best Practices

### Metadata Preparation Checklist

Before creating a release, prepare:

* [ ] Complete artist information (UUIDs or names)
* [ ] ISRC codes for all tracks
* [ ] UPC code for the release (if applicable)
* [ ] High-resolution artwork (minimum 3000x3000px)
* [ ] Accurate release and pre-release dates
* [ ] Complete contributor information with roles
* [ ] Genre classifications (main and sub-genres)
* [ ] Copyright and label information
* [ ] Explicit content ratings

### File Format Recommendations

**Audio Files:**

* Format: WAV, FLAC, or high-quality MP3
* Sample rate: 44.1 kHz or 48 kHz
* Bit depth: 16-bit or 24-bit
* Bitrate: 320 kbps (for MP3)

**Artwork:**

* Format: JPG or PNG
* Resolution: Minimum 3000x3000px
* Color mode: RGB
* File size: Under 10MB

**Video Files:**

* Format: MP4, MOV, or AVI
* Resolution: 1080p or 4K
* Codec: H.264 or H.265

### Error Handling Pattern

```javascript Node.js theme={null}
async function createRelease(releaseData) {
  try {
    const response = await fetch('https://api.royalti.io/releases', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(releaseData)
    });

    const result = await response.json();

    if (!response.ok) {
      throw new Error(result.error?.message || 'Failed to create release');
    }

    return result.data;
  } catch (error) {
    console.error('Release creation failed:', error.message);
    throw error;
  }
}
```

### Validation Before Submission

```javascript Node.js theme={null}
async function validateReleaseBeforeSubmit(releaseId) {
  const response = await fetch(`https://api.royalti.io/releases/${releaseId}`, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });

  const release = await response.json();

  const errors = [];

  // Validate tracks
  if (!release.data.tracks || release.data.tracks.length === 0) {
    errors.push('Release must have at least one track');
  }

  // Validate primary artist
  const hasPrimaryArtist = release.data.artists.some(a => a.type === 'primary');
  if (!hasPrimaryArtist) {
    errors.push('Release must have at least one primary artist');
  }

  // Validate media
  const tracksWithoutMedia = release.data.tracks.filter(
    t => !t.media || t.media.length === 0
  );
  if (tracksWithoutMedia.length > 0) {
    errors.push(`${tracksWithoutMedia.length} track(s) missing audio files`);
  }

  if (errors.length > 0) {
    throw new Error(`Validation failed:\n${errors.join('\n')}`);
  }

  return true;
}

// Usage
try {
  await validateReleaseBeforeSubmit(releaseId);
  await submitRelease(releaseId);
} catch (error) {
  console.error(error.message);
}
```

### Integration with DDEX

Releases integrate seamlessly with DDEX distribution:

```javascript Node.js theme={null}
// After release is completed, generate DDEX message
const ddexResponse = await fetch('https://api.royalti.io/ddex/generate-ern', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    productId: release.data.productId,  // From completed release
    providers: ['spotify', 'apple_music'],
    messageType: 'ERN'
  })
});
```

## Status Workflow

### Release Status Transitions

```
draft → submitted → under_review → approved → completed
                                      ↓
                                  rejected → draft (resubmit)
```

### Editable Statuses

Only releases in **'draft'** or **'rejected'** status can be edited:

* Update metadata
* Add/remove/reorder tracks
* Upload/delete media
* Update track information

### Admin-Only Operations

* Review releases (approve/reject)
* Revert release status
* View internal feedback

## Related Endpoints

### Core Release Operations

* [Create Release](/api-reference/release/post-releases)
* [Get Releases](/api-reference/release/get-releases)
* [Get Release by ID](/api-reference/release/get-releases-id)
* [Update Release](/api-reference/release/put-releases-id)
* [Delete Release](/api-reference/release/delete-releases-id)
* [Release Statistics](/api-reference/release/get-releases-stats)

### Workflow Operations

* [Submit Release](/api-reference/release/post-releases-id-submit)
* [Review Release (Admin)](/api-reference/release/post-releases-id-review)
* [Add Feedback](/api-reference/release/post-releases-id-feedback)
* [Revert Status (Admin)](/api-reference/release/post-releases-id-revert-status)

### Release Media

* [Upload Release Media Files](/api-reference/release/post-releases-id-media-files)
* [Submit Release Media Links](/api-reference/release/post-releases-id-media-links)
* [Get Release Media](/api-reference/release/get-releases-id-media)
* [Delete Release Media](/api-reference/release/delete-releases-id-media-id)

### Track Media

* [Upload Track Media File](/api-reference/release/post-releases-id-tracks-id-media-file)
* [Submit Track Media Link](/api-reference/release/post-releases-id-tracks-id-media-link)
* [Get Track Media](/api-reference/release/get-releases-id-tracks-id-media)
* [Delete Track Media](/api-reference/release/delete-releases-id-tracks-id-media-id)

### Track Management

* [Create Track](/api-reference/release/post-releases-id-tracks)
* [Update Track](/api-reference/release/put-releases-id-tracks-id)
* [Delete Track](/api-reference/release/delete-releases-id-tracks-id)
* [Reorder Tracks](/api-reference/release/post-releases-id-tracks-reorder)
* [Link Asset to Release](/api-reference/release/post-releases-id-tracks-link-asset)
