<!-- Gard Music Distributor — Markdown export aligned with /docs/music-distributor (catalog: code tokens only; full curl / Python / TS examples). -->

# Music Distributor API

_Public reference export — aligned with [**/docs/music-distributor**](https://back.gard-api.org/docs/music-distributor) (same sections, examples, and **code-only** catalog tables)._

## Authentication

**Base URL:** `https://back.gard-api.org`  
**Music Distributor base:** `https://back.gard-api.org/api/v1/music-distributor`  
**Header:** `X-API-Key: gard_…` (create in Dashboard → API Keys).

```bash
curl https://back.gard-api.org/api/v1/music-distributor/catalog/reference-data \
  -H "X-API-Key: gard_…"
```

## Media requirements

### Cover art (required unless backend relaxes — submit flow expects cover)

| Rule | Detail |
| --- | --- |
| Formats | JPEG or PNG only. |
| Square | Width must equal height. |
| Resolution | Between 1400×1400 and 6000×6000 px. |
| DPI | ≥ 72. |
| File size | ≤ 20 MB. |
| Colour | RGB (no CMYK-only uploads). |

### Audio (required: at least one file)

| Rule | Detail |
| --- | --- |
| Formats | WAV, FLAC, or MP3 on upload; server may convert to WAV for delivery. |
| Duration | Each track ≥ 4 seconds (validated server-side when ffprobe/wave available). |
| Size | ≤ 1 GB per file. |
| Naming | Use ASCII-safe filenames; order of files matches order of `tracks_meta` entries. |

### Video (optional — Apple Music style)

| Rule | Detail |
| --- | --- |
| Container | .mov or .mp4. |
| Resolution | 1920×1080 or 3840×2160 when validated. |
| Size | ≤ 6 GB. |

### Digital booklet (optional)

| Rule | Detail |
| --- | --- |
| Format | PDF only (valid %PDF- header). |
| Size | ≤ 10 MB. |

### URL-based upload (alternative to binary files)

| Rule | Detail |
| --- | --- |
| Supported fields | cover_url, audio_files_urls, video_url, booklet_url. |
| Format | Public HTTP(S) URLs only. Max 50 MB per URL. Max 30 audio URLs per request (`audio_files_urls`). |
| Mutual exclusion | Provide either binary file OR URL for each field — never both. |
| Cleanup | URL files are downloaded server-side, processed, and deleted after distributor upload. |

## Catalog reference (**code** tokens)

Use **`code`** values from these tables for multipart fields `genre_id`, `sub_genre_id`, entries inside JSON arrays `platforms`, `countries`, and for `meta_lang` / languages where applicable. The server still accepts legacy numeric ids, but **public documentation lists codes only** — identical to the interactive docs page.

### Platforms

_Bundled list `frontend/lib/music-distributor-catalog-bundled/docs-catalog-lists.json` (55 rows)._

| code | name |
| --- | --- |
| `7digital` | 7digital |
| `acrcloud` | ACRCloud |
| `amazon_music` | Amazon Music |
| `anghami` | Anghami |
| `apple_music` | Apple Music |
| `audiblemagic` | AudibleMagic |
| `awa` | AWA |
| `base_nda` | BASE_NDA |
| `beeline_kz` | BeeLine KZ |
| `beeline_t2_ringbacktone` | Beeline, t2 (RingBackTone) |
| `clicknclear` | ClicknClear |
| `cron_telecom` | Cron Telecom |
| `deezer` | Deezer |
| `flo` | FLO |
| `fonmix` | FonMix |
| `gomusic` | GoMusic |
| `iheart` | iHeart |
| `jaxsta` | Jaxsta |
| `jiosaavn` | JioSaavn |
| `kkbox` | KKBOX |
| `likee` | Likee |
| `line_music_rythm` | LINE MUSIC / Rythm |
| `lyricfind` | LyricFind |
| `megafon_ringbacktone` | MegaFon (RingBackTone) |
| `mixcloud` | Mixcloud |
| `mobi_music` | mobi music |
| `mobi_music_kz` | Mobi Music KZ |
| `mts_ringbacktone` | MTS (RingBackTone) |
| `musixmatch` | MusixMatch |
| `netease` | Netease |
| `other_distribution` | Other distribution |
| `pandora` | Pandora |
| `peloton` | Peloton |
| `presto_music` | Presto Music |
| `pretzel` | Pretzel |
| `rao_russian_authors_society` | RAO (Russian Authors' Society) |
| `ringbacktone_partner` | RingBackTone-Partner |
| `smule` | Smule |
| `soundcloud` | SoundCloud |
| `soundexchange` | SoundExchange |
| `spotify` | Spotify |
| `spotify_video` | Spotify Video |
| `tencent` | Tencent |
| `tidal` | TIDAL |
| `tiktok` | TikTok |
| `trebel` | TREBEL |
| `vk_music` | VK Music |
| `vk_video` | VK Video |
| `vois_russian_organization_for_intellectual_property` | VOIS (Russian Organization for Intellectual Property) |
| `yandex_music` | Yandex Music |
| `yandex_video` | Yandex Video |
| `youtube_sound_recording` | YouTube (Sound Recording) |
| `youtube_copyright` | YouTube Copyright |
| `youtube_music` | YouTube Music |
| `zvuk_wink_music` | Zvuk / Wink Music |

### Countries / territories

_Bundled list `frontend/lib/music-distributor-catalog-bundled/docs-catalog-lists.json` (248 rows)._

| code | name |
| --- | --- |
| `af` | Afghanistan |
| `ax` | Aland Islands |
| `al` | Albania |
| `dz` | Algeria |
| `as` | American Samoa |
| `ad` | Andorra |
| `ao` | Angola |
| `ai` | Anguilla |
| `aq` | Antarctica |
| `ag` | Antigua And Barbuda |
| `ar` | Argentina |
| `am` | Armenia |
| `aw` | Aruba |
| `au` | Australia |
| `at` | Austria |
| `az` | Azerbaijan |
| `bs` | Bahamas |
| `bh` | Bahrain |
| `bd` | Bangladesh |
| `bb` | Barbados |
| `by` | Belarus |
| `be` | Belgium |
| `bz` | Belize |
| `bj` | Benin |
| `bm` | Bermuda |
| `bt` | Bhutan |
| `bo` | Bolivia |
| `bq` | Bonaire |
| `ba` | Bosnia And Herzegowina |
| `bw` | Botswana |
| `bv` | Bouvet Island |
| `br` | Brazil |
| `io` | British Indian Ocean Territory |
| `vg` | British Virgin Islands |
| `bn` | Brunei Darussalam |
| `bg` | Bulgaria |
| `bf` | Burkina Faso |
| `bi` | Burundi |
| `kh` | Cambodia |
| `cm` | Cameroon |
| `ca` | Canada |
| `cv` | Cape Verde |
| `ky` | Cayman Islands |
| `cf` | Central African Republic |
| `td` | Chad |
| `cl` | Chile |
| `cx` | Christmas Island |
| `cis` | CIS |
| `cc` | Cocos (Keeling) Islands |
| `co` | Colombia |
| `km` | Comoros |
| `ck` | Cook Islands |
| `cr` | Costa Rica |
| `ci` | Cote D`Ivoire |
| `hr` | Croatia |
| `cu` | Cuba |
| `cy` | Cyprus |
| `cz` | Czech Republic |
| `kp` | Democratic People's Republic of Korea |
| `cd` | Democratic Republic of Congo |
| `dk` | Denmark |
| `dj` | Djibouti |
| `dm` | Dominica |
| `do` | Dominican Republic |
| `tl` | East Timor |
| `ec` | Ecuador |
| `eg` | Egypt |
| `sv` | El Salvador |
| `gq` | Equatorial Guinea |
| `er` | Eritrea |
| `ee` | Estonia |
| `et` | Ethiopia |
| `fk` | Falkland Islands (Malvinas) |
| `fo` | Faroe Islands |
| `fm` | Federal States of Micronesia |
| `fj` | Fiji |
| `fi` | Finland |
| `fr` | France |
| `gf` | French Guiana |
| `pf` | French Polynesia |
| `tf` | French Southern Territories |
| `ga` | Gabon |
| `gm` | Gambia |
| `ge` | Georgia |
| `de` | Germany |
| `gh` | Ghana |
| `gi` | Gibraltar |
| `gr` | Greece |
| `gl` | Greenland |
| `gd` | Grenada |
| `gp` | Guadeloupe |
| `gu` | Guam |
| `gt` | Guatemala |
| `gg` | Guernsey |
| `gn` | Guinea |
| `gw` | Guinea-Bissau |
| `gy` | Guyana |
| `ht` | Haiti |
| `hm` | Heard And Mc Donald Islands |
| `va` | Holy See (Vatican City State) |
| `hn` | Honduras |
| `hk` | Hong Kong |
| `hu` | Hungary |
| `is` | Iceland |
| `in` | India |
| `id` | Indonesia |
| `ir` | Iran |
| `iq` | Iraq |
| `ie` | Ireland |
| `im` | Isle of Man |
| `il` | Israel |
| `it` | Italy |
| `jm` | Jamaica |
| `jp` | Japan |
| `je` | Jersey |
| `jo` | Jordan |
| `kz` | Kazakhstan |
| `ke` | Kenya |
| `ki` | Kiribati |
| `xk` | Kosovo |
| `kw` | Kuwait |
| `kg` | Kyrgyzstan |
| `la` | Laos |
| `lv` | Latvia |
| `lb` | Lebanon |
| `ls` | Lesotho |
| `lr` | Liberia |
| `ly` | Libyan Arab Jamahiriya |
| `li` | Liechtenstein |
| `lt` | Lithuania |
| `lu` | Luxembourg |
| `mo` | Macau |
| `mk` | Macedonia |
| `mg` | Madagascar |
| `mw` | Malawi |
| `my` | Malaysia |
| `mv` | Maldives |
| `ml` | Mali |
| `mt` | Malta |
| `mh` | Marshall Islands |
| `mq` | Martinique |
| `mr` | Mauritania |
| `mu` | Mauritius |
| `yt` | Mayotte |
| `mx` | Mexico |
| `md` | Moldova |
| `mc` | Monaco |
| `mn` | Mongolia |
| `me` | Montenegro |
| `ms` | Montserrat |
| `ma` | Morocco |
| `mz` | Mozambique |
| `mm` | Myanmar |
| `na` | Namibia |
| `nr` | Nauru |
| `np` | Nepal |
| `nl` | Netherlands |
| `an` | Netherlands Antilles |
| `nc` | New Caledonia |
| `nz` | New Zealand |
| `ni` | Nicaragua |
| `ne` | Niger |
| `ng` | Nigeria |
| `nu` | Niue |
| `nf` | Norfolk Island |
| `mp` | Northern Mariana Islands |
| `no` | Norway |
| `om` | Oman |
| `pk` | Pakistan |
| `pw` | Palau |
| `ps` | Palestine |
| `pa` | Panama |
| `pg` | Papua New Guinea |
| `py` | Paraguay |
| `pe` | Peru |
| `ph` | Philippines |
| `pn` | Pitcairn |
| `pl` | Poland |
| `pt` | Portugal |
| `cn` | PRC |
| `pr` | Puerto Rico |
| `qa` | Qatar |
| `cg` | Republic of Congo |
| `kr` | Republic of Korea |
| `re` | Reunion |
| `ro` | Romania |
| `ru` | Russian Federation |
| `rw` | Rwanda |
| `kn` | Saint Kitts And Nevis |
| `lc` | Saint Lucia |
| `vc` | Saint Vincent And The Grenadines |
| `ws` | Samoa |
| `sm` | San Marino |
| `st` | Sao Tome And Principe |
| `sa` | Saudi Arabia |
| `sn` | Senegal |
| `rs` | Serbia |
| `sc` | Seychelles |
| `sl` | Sierra Leone |
| `sg` | Singapore |
| `sk` | Slovakia |
| `si` | Slovenia |
| `sb` | Solomon Islands |
| `so` | Somalia |
| `za` | South Africa |
| `gs` | South Georgia And South S.S. |
| `ss` | South Sudan |
| `es` | Spain |
| `lk` | Sri Lanka |
| `sh` | St. Helena |
| `pm` | St. Pierre And Miquelon |
| `sd` | Sudan |
| `sr` | Suriname |
| `sj` | Svalbard And Jan Mayen Islands |
| `sz` | Swaziland |
| `se` | Sweden |
| `ch` | Switzerland |
| `sy` | Syrian Arab Republic |
| `tw` | Taiwan |
| `tj` | Tajikistan |
| `tz` | Tanzania |
| `th` | Thailand |
| `tg` | Togo |
| `tk` | Tokelau |
| `to` | Tonga |
| `tt` | Trinidad And Tobago |
| `tn` | Tunisia |
| `tr` | Turkey |
| `tm` | Turkmenistan |
| `tc` | Turks And Caicos Islands |
| `tv` | Tuvalu |
| `um` | U.S. Minor Islands |
| `ug` | Uganda |
| `ua` | Ukraine |
| `ae` | United Arab Emirates |
| `gb` | United Kingdom |
| `us` | United States |
| `vi` | United States Virgin Islands |
| `uy` | Uruguay |
| `uz` | Uzbekistan |
| `vu` | Vanuatu |
| `ve` | Venezuela |
| `vn` | Viet Nam |
| `wf` | Wallis And Futuna Islands |
| `eh` | Western Sahara |
| `ye` | Yemen |
| `zm` | Zambia |
| `zw` | Zimbabwe |

### Languages

_Bundled list `frontend/lib/music-distributor-catalog-bundled/docs-catalog-lists.json` (65 rows)._

| code | name |
| --- | --- |
| `ae` | Avestan |
| `az` | Azeri |
| `en` | English |
| `ar` | Arabic |
| `hy` | Armenian |
| `af` | Afrikaans |
| `be` | Belarusian |
| `bn` | Bengali |
| `bg` | Bulgarian |
| `hu` | Hungarian |
| `vi` | Vietnamese |
| `ht` | Haitian |
| `el` | Greek |
| `ka` | Georgian |
| `da` | Danish |
| `zu` | Zulu |
| `he` | Hebrew |
| `id` | Indonesian |
| `ga` | Irish |
| `is` | Icelandic |
| `es` | Spanish |
| `it` | Italian |
| `kk` | Kazakh |
| `ca` | Catalan |
| `ky` | Kyrgyz |
| `zh` | Chinese |
| `ko` | Korean |
| `lo` | Lao |
| `la` | Latin |
| `lv` | Latvian |
| `lt` | Lithuanian |
| `ms` | Malay |
| `de` | German |
| `nl` | Dutch |
| `no` | Norwegian |
| `pa` | Punjabi |
| `fa` | Persian |
| `pl` | Polish |
| `pt` | Portuguese |
| `ro` | Romanian |
| `ru` | Russian |
| `sa` | Sanskrit |
| `sk` | Slovak |
| `sl` | Slovenian |
| `tl` | Tagalog |
| `tg` | Tajik |
| `th` | Thai |
| `ta` | Tamil |
| `tt` | Tatar |
| `te` | Telugu |
| `tr` | Turkish |
| `tk` | Turkmen |
| `uz` | Uzbek |
| `uk` | Ukrainian |
| `ur` | Urdu |
| `fi` | Finnish |
| `fr` | French |
| `hi` | Hindi |
| `hr` | Croatian |
| `ce` | CE |
| `cs` | Czech |
| `cv` | CV |
| `sv` | Swedish |
| `et` | Estonian |
| `ja` | Japanese |

### Genres (root)

_Bundled list `frontend/lib/music-distributor-catalog-bundled/docs-catalog-lists.json` (46 rows)._

| code | name |
| --- | --- |
| `alternative` | Alternative |
| `anime` | Anime |
| `arabic` | Arabic |
| `armenian` | Armenian |
| `blues` | Blues |
| `brazilian` | Brazilian |
| `children_s_music` | Children's Music |
| `chinese` | Chinese |
| `christian_gospel` | Christian & Gospel |
| `classical` | Classical |
| `comedy` | Comedy |
| `country` | Country |
| `cuban` | Cuban |
| `dance` | Dance |
| `disney` | Disney |
| `easy_listening` | Easy Listening |
| `electronic` | Electronic |
| `enka` | Enka |
| `fitness_workout` | Fitness & Workout |
| `folk` | Folk |
| `french_pop` | French Pop |
| `german_folk` | German Folk |
| `german_pop` | German Pop |
| `hip_hop_rap` | Hip Hop/Rap |
| `holiday` | Holiday |
| `indian` | Indian |
| `inspirational` | Inspirational |
| `instrumental` | Instrumental |
| `j_pop` | J-Pop |
| `jazz` | Jazz |
| `karaoke` | Karaoke |
| `kayokyoku` | Kayokyoku |
| `korean` | Korean |
| `latin` | Latin |
| `marching_bands` | Marching Bands |
| `new_age` | New Age |
| `pop` | Pop |
| `r_b_soul` | R&B/Soul |
| `reggae` | Reggae |
| `rock` | Rock |
| `russian` | Russian |
| `singer_songwriter` | Singer/Songwriter |
| `soundtrack` | Soundtrack |
| `spoken_word` | Spoken Word |
| `vocal` | Vocal |
| `world` | World |

### Subgenres (by parent genre **code**)

#### Parent `alternative` — Alternative

| code | name |
| --- | --- |
| `adult_alternative` | Adult Alternative |
| `alternative_metal` | Alternative Metal |
| `alternative_rock` | Alternative Rock |
| `chinese_alt` | Chinese Alt |
| `college_rock` | College Rock |
| `egyptian_tarab` | Egyptian Tarab |
| `emo` | EMO |
| `emo_rap` | Emo rap |
| `goth_rock` | Goth Rock |
| `grunge` | Grunge |
| `hardcore_punk` | Hardcore punk |
| `indie_egyptian` | Indie Egyptian |
| `indie_levant` | Indie Levant |
| `indie_maghreb` | Indie Maghreb |
| `indie_pop` | Indie Pop |
| `indie_rock` | Indie Rock |
| `iraqi_tarab` | Iraqi Tarab |
| `khaleeji_tarab` | Khaleeji Tarab |
| `korean_indie` | Korean Indie |
| `metalcore` | Metalcore |
| `new_wave` | New Wave |
| `pop_punk` | Pop Punk |
| `post_hardcore` | Post-hardcore |
| `punk` | Punk |
| `rap_metal` | Rap metal |

#### Parent `anime` — Anime

_No subgenres._

#### Parent `arabic` — Arabic

| code | name |
| --- | --- |
| `arabic_pop` | Arabic Pop |
| `dabke` | Dabke |
| `islamic` | Islamic |
| `khaleeji` | Khaleeji |
| `levant` | Levant |
| `maghreb_rai` | Maghreb Rai |
| `north_african` | North African |

#### Parent `armenian` — Armenian

_No subgenres._

#### Parent `blues` — Blues

| code | name |
| --- | --- |
| `acoustic_blues` | Acoustic Blues |
| `chicago_blues` | Chicago Blues |
| `classic_blues` | Classic Blues |
| `contemporary_blues` | Contemporary Blues |
| `country_blues` | Country Blues |
| `delta_blues` | Delta Blues |
| `electric_blues` | Electric Blues |

#### Parent `brazilian` — Brazilian

| code | name |
| --- | --- |
| `ax` | Axé |
| `baile_funk` | Baile Funk |
| `bossa_nova` | Bossa Nova |
| `choro` | Choro |
| `forr` | Forró |
| `frevo` | Frevo |
| `mpb` | MPB |
| `pagode` | Pagode |
| `samba` | Samba |
| `sertanejo` | Sertanejo |

#### Parent `children_s_music` — Children's Music

| code | name |
| --- | --- |
| `fairytales` | Fairytales |
| `lullabies` | Lullabies |
| `sing_along` | Sing-Along |
| `stories` | Stories |

#### Parent `chinese` — Chinese

| code | name |
| --- | --- |
| `chinese_classical` | Chinese Classical |
| `chinese_flute` | Chinese Flute |
| `chinese_opera` | Chinese Opera |
| `chinese_orchestral` | Chinese Orchestral |
| `chinese_regional_folk` | Chinese Regional Folk |
| `chinese_strings` | Chinese Strings |
| `taiwanese_folk` | Taiwanese Folk |
| `tibetan_native_music` | Tibetan Native Music |

#### Parent `christian_gospel` — Christian & Gospel

| code | name |
| --- | --- |
| `ccm` | CCM |
| `christian_metal` | Christian Metal |
| `christian_pop` | Christian Pop |
| `christian_rap` | Christian Rap |
| `christian_rock` | Christian Rock |
| `classic_christian` | Classic Christian |
| `contemporary_gospel` | Contemporary Gospel |
| `gospel` | Gospel |
| `praise_worship` | Praise & Worship |
| `southern_gospel` | Southern Gospel |
| `traditional_gospel` | Traditional Gospel |

#### Parent `classical` — Classical

| code | name |
| --- | --- |
| `art_song` | Art Song |
| `avant_garde` | Avant-Garde |
| `baroque_era` | Baroque Era |
| `brass_woodwinds` | Brass & Woodwinds |
| `cantata` | Cantata |
| `cello` | Cello |
| `chamber_music` | Chamber Music |
| `chant` | Chant |
| `choral` | Choral |
| `classical_crossover` | Classical Crossover |
| `classical_electronic` | Classical Electronic |
| `classical_era` | Classical Era |
| `contemporary_era` | Contemporary Era |
| `guitar` | Guitar |
| `impressionist` | Impressionist |
| `medieval_era` | Medieval Era |
| `minimalism` | Minimalism |
| `modern_era` | Modern Era |
| `opera` | Opera |
| `oratorio` | Oratorio |
| `orchestral` | Orchestral |
| `percussion` | Percussion |
| `piano` | Piano |
| `renaissance` | Renaissance |
| `romantic_era` | Romantic Era |
| `sacred` | Sacred |
| `solo_instrumental` | Solo Instrumental |
| `violin` | Violin |

#### Parent `comedy` — Comedy

| code | name |
| --- | --- |
| `novelty` | Novelty |
| `standup_comedy` | Standup Comedy |

#### Parent `country` — Country

| code | name |
| --- | --- |
| `alternative_country` | Alternative Country |
| `americana` | Americana |
| `bluegrass` | Bluegrass |
| `contemporary_bluegrass` | Contemporary Bluegrass |
| `contemporary_country` | Contemporary Country |
| `country_gospel` | Country Gospel |
| `honky_tonk` | Honky Tonk |
| `outlaw_country` | Outlaw Country |
| `thai_country` | Thai Country |
| `traditional_bluegrass` | Traditional Bluegrass |
| `traditional_country` | Traditional Country |
| `urban_cowboy` | Urban Cowboy |

#### Parent `cuban` — Cuban

| code | name |
| --- | --- |
| `bolero` | Bolero |
| `chachacha` | Chachacha |
| `guajira` | Guajira |
| `guaracha` | Guaracha |
| `mambo` | Mambo |
| `son` | Son |
| `timba` | Timba |

#### Parent `dance` — Dance

| code | name |
| --- | --- |
| `breakbeat` | Breakbeat |
| `edm` | EDM |
| `garage` | Garage |
| `hardcore` | Hardcore |
| `house` | House |
| `jungle_drum_n_bass` | Jungle/Drum'n'bass |
| `maghreb_dance` | Maghreb Dance |
| `phonk_fonk` | Phonk/Fonk |
| `tech_house` | Tech House |
| `techno` | Techno |
| `trance` | Trance |

#### Parent `disney` — Disney

_No subgenres._

#### Parent `easy_listening` — Easy Listening

| code | name |
| --- | --- |
| `lounge` | Lounge |
| `swing` | Swing |

#### Parent `electronic` — Electronic

| code | name |
| --- | --- |
| `ambient` | Ambient |
| `bass` | Bass |
| `downtempo` | Downtempo |
| `dubstep` | Dubstep |
| `electro_cha_abi` | Electro-Cha'abi |
| `electronica` | Electronica |
| `idm_experimental` | IDM/Experimental |
| `industrial` | Industrial |
| `levant_electronic` | Levant Electronic |
| `maghreb_electronic` | Maghreb Electronic |

#### Parent `enka` — Enka

_No subgenres._

#### Parent `fitness_workout` — Fitness & Workout

_No subgenres._

#### Parent `folk` — Folk

| code | name |
| --- | --- |
| `iraqi_folk` | Iraqi Folk |
| `khaleeji_folk` | Khaleeji Folk |

#### Parent `french_pop` — French Pop

_No subgenres._

#### Parent `german_folk` — German Folk

_No subgenres._

#### Parent `german_pop` — German Pop

_No subgenres._

#### Parent `hip_hop_rap` — Hip Hop/Rap

| code | name |
| --- | --- |
| `alternative_rap` | Alternative Rap |
| `chillhop` | Chillhop |
| `chinese_hip_hop` | Chinese Hip-Hop |
| `dirty_south` | Dirty South |
| `east_coast_rap` | East Coast Rap |
| `egyptian_hip_hop` | Egyptian Hip-Hop |
| `gangsta_rap` | Gangsta Rap |
| `hardcore_rap` | Hardcore Rap |
| `hip_hop` | Hip-Hop |
| `khaleeji_hip_hop` | Khaleeji Hip-Hop |
| `korean_hip_hop` | Korean Hip-Hop |
| `latin_rap` | Latin Rap |
| `levant_hip_hop` | Levant Hip-Hop |
| `lofi_hip_hop` | Lofi Hip Hop |
| `maghreb_hip_hop` | Maghreb Hip-Hop |
| `old_school_rap` | Old School Rap |
| `rap` | Rap |
| `russian_hip_hop` | Russian Hip-Hop |
| `uk_hip_hop` | UK Hip Hop |
| `underground_rap` | Underground Rap |
| `west_coast_rap` | West Coast Rap |

#### Parent `holiday` — Holiday

| code | name |
| --- | --- |
| `chanukah` | Chanukah |
| `christmas` | Christmas |
| `christmas_children_s` | Christmas: Children's |
| `christmas_classic` | Christmas: Classic |
| `christmas_classical` | Christmas: Classical |
| `christmas_jazz` | Christmas: Jazz |
| `christmas_modern` | Christmas: Modern |
| `christmas_pop` | Christmas: Pop |
| `christmas_r_b` | Christmas: R&B |
| `christmas_religious` | Christmas: Religious |
| `christmas_rock` | Christmas: Rock |
| `easter` | Easter |
| `halloween` | Halloween |
| `thanksgiving` | Thanksgiving |

#### Parent `indian` — Indian

| code | name |
| --- | --- |
| `bollywood` | Bollywood |
| `devotional_spiritual` | Devotional & Spiritual |
| `ghazals` | Ghazals |
| `indian_classical` | Indian Classical |
| `indian_folk` | Indian Folk |
| `indian_pop` | Indian Pop |
| `punjabi_pop` | Punjabi Pop |
| `rabindra_sangeet` | Rabindra Sangeet |
| `regional_indian` | Regional Indian |
| `sufi` | Sufi |
| `tamil` | Tamil |
| `telugu` | Telugu |

#### Parent `inspirational` — Inspirational

_No subgenres._

#### Parent `instrumental` — Instrumental

_No subgenres._

#### Parent `j_pop` — J-Pop

_No subgenres._

#### Parent `jazz` — Jazz

| code | name |
| --- | --- |
| `avant_garde_jazz` | Avant-Garde Jazz |
| `bebop` | Bebop |
| `big_band` | Big Band |
| `contemporary_jazz` | Contemporary Jazz |
| `cool` | Cool |
| `crossover_jazz` | Crossover Jazz |
| `dixieland` | Dixieland |
| `fusion` | Fusion |
| `hard_bop` | Hard Bop |
| `latin_jazz` | Latin Jazz |
| `mainstream_jazz` | Mainstream Jazz |
| `ragtime` | Ragtime |
| `smooth_jazz` | Smooth Jazz |
| `trad_jazz` | Trad Jazz |
| `vocal_jazz` | Vocal Jazz |

#### Parent `karaoke` — Karaoke

_No subgenres._

#### Parent `kayokyoku` — Kayokyoku

_No subgenres._

#### Parent `korean` — Korean

| code | name |
| --- | --- |
| `korean_traditional` | Korean Traditional |

#### Parent `latin` — Latin

| code | name |
| --- | --- |
| `alternative_rock_in_spanish` | Alternative & Rock in Spanish |
| `baladas_y_boleros` | Baladas y Boleros |
| `contemporary_latin` | Contemporary Latin |
| `latin_jazz` | Latin Jazz |
| `latin_urban` | Latin Urban |
| `pop_in_spanish` | Pop in Spanish |
| `raices` | Raices |
| `regional_mexicano` | Regional Mexicano |
| `salsa_y_tropical` | Salsa y Tropical |

#### Parent `marching_bands` — Marching Bands

_No subgenres._

#### Parent `new_age` — New Age

| code | name |
| --- | --- |
| `healing` | Healing |
| `meditation` | Meditation |
| `nature` | Nature |
| `relaxation` | Relaxation |
| `travel` | Travel |
| `yoga` | Yoga |

#### Parent `pop` — Pop

| code | name |
| --- | --- |
| `adult_contemporary` | Adult Contemporary |
| `britpop` | BritPop |
| `cantopop` | Cantopop |
| `egyptian_pop` | Egyptian Pop |
| `hyperpop` | Hyperpop |
| `indo_pop` | Indo Pop |
| `iraqi_pop` | Iraqi Pop |
| `k_pop` | K-Pop |
| `khaleeji_pop` | Khaleeji Pop |
| `korean_folk_pop` | Korean Folk-Pop |
| `levant_pop` | Levant Pop |
| `maghreb_pop` | Maghreb Pop |
| `malaysian_pop` | Malaysian Pop |
| `mandopop` | Mandopop |
| `manilla_sound` | Manilla Sound |
| `oldies` | Oldies |
| `original_pilipino_music` | Original Pilipino Music |
| `pinoy_pop` | Pinoy Pop |
| `pop_rock` | Pop/Rock |
| `russian_pop` | Russian Pop |
| `soft_rock` | Soft Rock |
| `tai_pop` | Tai-Pop |
| `teen_pop` | Teen Pop |
| `thai_pop` | Thai Pop |

#### Parent `r_b_soul` — R&B/Soul

| code | name |
| --- | --- |
| `contemporary_r_b` | Contemporary R&B |
| `disco` | Disco |
| `doo_wop` | Doo Wop |
| `funk` | Funk |
| `motown` | Motown |
| `neo_soul` | Neo-Soul |
| `soul` | Soul |

#### Parent `reggae` — Reggae

| code | name |
| --- | --- |
| `dub` | Dub |
| `lovers_rock` | Lovers Rock |
| `modern_dancehall` | Modern Dancehall |
| `roots_reggae` | Roots Reggae |
| `ska` | Ska |

#### Parent `rock` — Rock

| code | name |
| --- | --- |
| `american_trad_rock` | American Trad Rock |
| `arena_rock` | Arena Rock |
| `blues_rock` | Blues-Rock |
| `british_invasion` | British Invasion |
| `chinese_rock` | Chinese Rock |
| `death_metal_black_metal` | Death Metal/Black Metal |
| `epic_rock` | Epic Rock |
| `glam_rock` | Glam Rock |
| `hair_metal` | Hair Metal |
| `hard_rock` | Hard Rock |
| `heavy_metal` | Heavy Metal |
| `jam_bands` | Jam Bands |
| `korean_rock` | Korean Rock |
| `metal` | Metal |
| `nu_metal` | Nu metal |
| `power_metal` | Power Metal |
| `prog_rock_art_rock` | Prog-Rock/Art Rock |
| `progressive_metal` | Progressive metal |
| `psychedelic` | Psychedelic |
| `rock_roll` | Rock & Roll |
| `rockabilly` | Rockabilly |
| `roots_rock` | Roots Rock |
| `russian_rock` | Russian Rock |
| `singer_songwriter` | Singer/Songwriter |
| `southern_rock` | Southern Rock |
| `surf` | Surf |
| `tex_mex` | Tex-Mex |

#### Parent `russian` — Russian

| code | name |
| --- | --- |
| `russian_bard` | Russian Bard |
| `russian_chanson` | Russian Chanson |
| `russian_romance` | Russian Romance |

#### Parent `singer_songwriter` — Singer/Songwriter

| code | name |
| --- | --- |
| `alternative_folk` | Alternative Folk |
| `contemporary_folk` | Contemporary Folk |
| `contemporary_singer_songwriter` | Contemporary Singer/Songwriter |
| `folk_rock` | Folk-Rock |
| `new_acoustic` | New Acoustic |
| `traditional_folk` | Traditional Folk |

#### Parent `soundtrack` — Soundtrack

| code | name |
| --- | --- |
| `foreign_cinema` | Foreign Cinema |
| `musicals` | Musicals |
| `original_score` | Original Score |
| `sound_effects` | Sound Effects |
| `soundtrack` | Soundtrack |
| `tv_soundtrack` | TV Soundtrack |
| `video_game` | Video Game |

#### Parent `spoken_word` — Spoken Word

_No subgenres._

#### Parent `vocal` — Vocal

| code | name |
| --- | --- |
| `standards` | Standards |
| `traditional_pop` | Traditional Pop |
| `trot` | Trot |
| `vocal_pop` | Vocal Pop |

#### Parent `world` — World

| code | name |
| --- | --- |
| `africa` | Africa |
| `afrikaans` | Afrikaans |
| `afro_beat` | Afro-Beat |
| `afro_pop` | Afro-Pop |
| `arabesque` | Arabesque |
| `asia` | Asia |
| `australia` | Australia |
| `azerbaijani` | Azerbaijani |
| `cajun` | Cajun |
| `calypso` | Calypso |
| `caribbean` | Caribbean |
| `caucasian` | Caucasian |
| `celtic` | Celtic |
| `celtic_folk` | Celtic Folk |
| `contemporary_celtic` | Contemporary Celtic |
| `dangdut` | Dangdut |
| `dini` | Dini |
| `europe` | Europe |
| `fado` | Fado |
| `farsi` | Farsi |
| `flamenco` | Flamenco |
| `france` | France |
| `georgian` | Georgian |
| `halk` | Halk |
| `hawaii` | Hawaii |
| `iberia` | Iberia |
| `indonesian_religious` | Indonesian Religious |
| `israeli` | Israeli |
| `japan` | Japan |
| `klezmer` | Klezmer |
| `north_america` | North America |
| `polka` | Polka |
| `russian` | Russian |
| `sanat` | Sanat |
| `soca` | Soca |
| `south_africa` | South Africa |
| `south_america` | South America |
| `tango` | Tango |
| `tatar` | Tatar |
| `traditional_celtic` | Traditional Celtic |
| `turkish` | Turkish |
| `worldbeat` | Worldbeat |
| `zydeco` | Zydeco |

## Track metadata field names (`tracks_meta`)

Each `tracks_meta[i]` aligns with `audio_files[i]` (same order). Fields include:

`name, version, isrc, track_po_code, author_rights, related_rights, explicit_content, is_cover, is_remix, is_instrumental, is_focus_track, is_live, is_drugs, preview_start, meta_lang, lyrics, persons (array of { name, role, order? }) — roles: artist, composer, songwriter (required)`

## Endpoint index

| Method | Path | Summary |
| --- | --- | --- |
| POST | `/api/v1/music-distributor/moderation/` | Submit a full release (multipart). The response includes a `status` field for the submission. |
| GET | `/api/v1/music-distributor/moderation/` | List submissions: `{ code, msg, submissions: [...] }`. Each row: `status` + human `message` (vendor-neutral). |
| GET | `/api/v1/music-distributor/catalog/reference-data` | One JSON snapshot: **platforms**, **countries**, **languages**, **genres_root** (each `{code, name}`), **subgenres_by_parent_code** (root genre code → subgenres), and optional **live_supplement** (platform groups, lines, price categories). Send **`X-API-Key: gard_…`**. You can cache this response in your integration. |
| GET | `/api/v1/music-distributor/catalog/platforms` | List DSP **platforms** as `{id, name, platform_name}` from the live catalog cache. Prefer **`GET /catalog/reference-data`** for `{code, name}` rows aligned with **`POST /moderation/`** (`platforms` field). Same auth as other catalog routes. |
| GET | `/api/v1/music-distributor/catalog/platform-groups` | Platform groupings from cache (for UI filters). **`reference-data`** may also include **`live_supplement.platform_groups`**. |
| GET | `/api/v1/music-distributor/releases/all` | List releases in your catalog. Optional `search`, `offset`, `limit`. Each row includes **`release_id`** (numeric catalog id for `GET …/releases/{release_ref}/status`), **`id`** / **`public_id`** (`rel_…`), **`status`** / **`message`** (public workflow — same vocabulary as **`GET /moderation/`**), plus metadata. **`admin`** users may see extra read-only fields (`internal_catalog_status`, `upstream_album_id`). |
| GET | `/api/v1/music-distributor/releases/{release_ref}` | Get one release. **`{release_ref}`** may be: numeric **`release_id`**, catalog **`rel_…`**, or moderation submission **`mdr_…`** (same resolution rules as **GET …/status**). **`status`** / **`message`** are the public workflow. Raw distributor fields (`upstream_status_data`, `upstream_album_id`, `internal_catalog_status`) are returned **only** for **`admin`**. |
| GET | `/api/v1/music-distributor/releases/{release_ref}/status` | Live distributor snapshot for the release. Path **`{release_ref}`** accepts: **(1)** numeric catalog **`release_id`** (`md_releases.id`, also returned as **`id`** in this response and in **`GET /releases/all`** as **`release_id`**), **(2)** catalog **`rel_…`**, **(3)** moderation **`mdr_…`** (your **`POST /moderation/`** `id`; resolves to the linked catalog row, then calls the distributor with the stored upstream album id). |
| POST | `/api/v1/music-distributor/releases/{release_ref}/sync` | Re-fetch status and metadata (same as GET …/status). **`{release_ref}`** accepts numeric id, **`rel_…`**, or **`mdr_…`**. |
| GET | `/api/v1/music-distributor/releases/{release_ref}/cover` | Binary cover art. **`{release_ref}`**: numeric id, **`rel_…`**, or **`mdr_…`**. |
| GET | `/api/v1/music-distributor/releases/persons/search?query=…` | Search people in the distributor directory (for credits). |
| POST | `/api/v1/music-distributor/releases/persons` | Body: { content_name: string }. Create a person entry. |
| GET | `/api/v1/music-distributor/releases/{release_ref}/video-clips` | Album video clips list. |
| GET | `/api/v1/music-distributor/releases/{release_ref}/track-video-clips` | Per-track video clips. |
| GET | `/api/v1/music-distributor/releases/{release_ref}/persons` | Album person links. |
| POST | `/api/v1/music-distributor/releases/{release_ref}/persons` | Add album person (body per backend). |
| GET | `/api/v1/music-distributor/releases/{release_ref}/track-persons` | Track person links. |
| POST | `/api/v1/music-distributor/releases/{release_ref}/track-persons` | Add track person. |
| POST | `/api/v1/music-distributor/releases/{release_ref}/sort-tracks` | Reorder tracks (body per backend). |
| GET | `/api/v1/music-distributor/releases/{release_ref}/platform-links` | DSP storefront links. Returns **sale_platforms** as **{ platform_name, link }** for all available platforms: **Wink**, **MTS**, **Yandex Music**, **Spotify**, **VK Music**, **Zvuk**. |
| POST | `/api/v1/music-distributor/releases/{release_ref}/revoke` | Distributor **platform moderation** withdraw or catalog drop: if the live upstream snapshot maps to internal **`under_review`** (staff/platform review, `can_revoke` + `comment_time`, codes 1/5, `moderation` / `onedit`), calls upstream **revoke** and sets the catalog row to **draft**. If not, **only removes your Gard catalog row** (same as `DELETE …/releases/{release_ref}` — no upstream revoke). **400** if the release is already **`live`** — use `POST /delete-requests/` instead. |
| POST | `/api/v1/music-distributor/delete-requests/` | Takedown queue for releases **already live** on DSPs. **Only accepted when the catalog row’s public `status` is `live`** (same rules as `GET /releases/{release_ref}`); otherwise **400** with the current status — use `POST …/revoke` or `DELETE …/releases/{release_ref}` for pre-live catalog/moderation handling. The request is processed by the Gard team — poll `GET /delete-requests/`. |
| GET | `/api/v1/music-distributor/delete-requests/` | List all takedown requests you have submitted. Status: pending → completed → rejected. |
| GET | `/api/v1/music-distributor/panel/scope` | Dashboard: artists + releases in your scope. Each release includes **`release_id`** (numeric catalog id), **`status`** / **`message`** (public workflow), and optional **`admin`**-only debug fields. |
| GET | `/api/v1/music-distributor/panel/activity-log` | Aggregated activity. Query: artist, action, limit, offset. |
| GET | `/api/v1/music-distributor/panel/reports/streaming.csv` | CSV export of your releases (400 if none). |
| POST | `/api/v1/music-distributor/pitch/` | Editorial pitch while the release is **not yet `live`** in the public workflow (same status resolution as `GET /moderation/`). Multipart + `payload_json` string. **400** once **`live`**. |
| GET | `/api/v1/music-distributor/pitch/` | List your pitch requests (all statuses: pending, in_progress, completed, rejected). |
| GET | `/api/v1/music-distributor/payout/settings` | Payout method + details. |
| PUT | `/api/v1/music-distributor/payout/settings` | Set payout. JSON: { method: paypal\|bank_account\|card_swift\|card_ru, details?: { … } }. |
| GET | `/api/v1/music-distributor/payout/withdrawals` | List withdrawals (query limit). |
| POST | `/api/v1/music-distributor/payout/withdrawals/request` | Request a withdrawal. JSON: { amount_cents, currency } — min 100 cents. |
| POST | `/api/v1/music-distributor/analytics/releases` | ★ Recommended. Batch analytics for up to 100 releases (rel_… and/or mdr_… — mix allowed) in one request. Returns per-release totals, per-platform streams, and per-track (ISRC) breakdowns for the chosen period. Served from the daily report (md_analytics_stream_facts) — no live upstream call. |
| GET | `/api/v1/music-distributor/analytics/summary/filters` | Analytics filter metadata (catalog-scoped). |
| POST | `/api/v1/music-distributor/analytics/summary/table` | Cross-store **table** (all DSPs combined in this upstream view). Minimal POST body; Gard adds date range and Cabinet **custom_filters** from your catalog. |
| POST | `/api/v1/music-distributor/analytics/spotify/table` | Spotify analytics table (JSON body). Same minimal POST contract as summary analytics. |
| POST | `/api/v1/music-distributor/analytics/applemusic/table` | Apple Music analytics table. |
| GET | `/api/v1/music-distributor/analytics/spotify/filters` | Spotify analytics filter metadata (catalog-scoped). Same prerequisite as other analytics routes. |
| POST | `/api/v1/music-distributor/analytics/spotify/graph` | Spotify — daily time-series graph. |
| POST | `/api/v1/music-distributor/analytics/spotify/bar` | Spotify — bar chart payload (proxied). |
| POST | `/api/v1/music-distributor/analytics/summary/graph/main` | Cross-store summary — main trend graph. |
| POST | `/api/v1/music-distributor/analytics/summary/graph/total` | Cross-store summary — totals graph. |
| POST | `/api/v1/music-distributor/analytics/summary/graph/country` | Cross-store summary — breakdown by country. |
| POST | `/api/v1/music-distributor/analytics/summary/graph/os` | Cross-store summary — breakdown by OS. |
| POST | `/api/v1/music-distributor/analytics/summary/graph/device_type` | Cross-store summary — breakdown by device type. |
| POST | `/api/v1/music-distributor/analytics/summary/graph/age` | Cross-store summary — age buckets (whole-catalog only, not per-release). |
| POST | `/api/v1/music-distributor/analytics/summary/graph/gender` | Cross-store summary — gender breakdown (whole-catalog only, not per-release). |
| POST | `/api/v1/music-distributor/analytics/summary/stats` | Cross-store summary — per-platform totals for the caller's catalog or a release/artist subset. |
| GET | `/api/v1/music-distributor/analytics/applemusic/filters` | Apple Music analytics filter metadata. |
| POST | `/api/v1/music-distributor/analytics/applemusic/graph` | Apple Music — graph series. |
| POST | `/api/v1/music-distributor/analytics/applemusic/graph/total` | Apple Music — totals graph. |
| POST | `/api/v1/music-distributor/analytics/applemusic/bar` | Apple Music — bar chart. |
| GET | `/api/v1/music-distributor/analytics/vkclips/filters` | VK Clips analytics filter metadata. |
| POST | `/api/v1/music-distributor/analytics/vkclips/table` | VK Clips analytics table. |
| POST | `/api/v1/music-distributor/analytics/vkclips/graph` | VK Clips — graph. |
| POST | `/api/v1/music-distributor/analytics/vkclips/graph/total` | VK Clips — totals graph. |
| POST | `/api/v1/music-distributor/analytics/yandex/table` | Yandex Music — analytics table. |
| POST | `/api/v1/music-distributor/analytics/yandex/graph` | Yandex Music — daily graph. |
| POST | `/api/v1/music-distributor/analytics/umavk/table` | UMA / VK music — analytics table. |
| POST | `/api/v1/music-distributor/analytics/umavk/graph` | UMA / VK music — daily graph. |
| POST | `/api/v1/music-distributor/analytics/mts/table` | MTS Music — analytics table. |
| POST | `/api/v1/music-distributor/analytics/mts/graph` | MTS Music — daily graph. |
| POST | `/api/v1/music-distributor/analytics/zvooq/table` | Zvooq — analytics table. |
| POST | `/api/v1/music-distributor/analytics/zvooq/graph` | Zvooq — daily graph. |

---

## POST `/api/v1/music-distributor/moderation/`

Submit a full release (multipart). The response includes a `status` field for the submission.

Booleans in form fields are strings: true/false/1/yes/on. JSON-array fields (`platforms`, `countries`, `artist_roles`, `tracks_meta`, …) must be valid JSON strings. **Credits:** Single 500 · EP 700 · Album/Compilation 850 (402 if balance too low). **Track count limits:** Single = 1 track, EP / Mini-Album = 2–6, Album / Compilation = 7–30 (>30 → 422). `tracks_meta` must have exactly one entry per audio file. **`callback_url`**: webhooks include **`X-Gard-Signature`** — verify with `GET /api/v1/keys/{id}/webhook-signing-secret` (see `docs/music-distributor.md`).

### Request fields

| Field | Type | Required | Description | Options |
| --- | --- | --- | --- | --- |
| release_name | string | yes | Release / album title. |  |
| artist_name | string | yes | Primary artist display name. |  |
| release_date | string (YYYY-MM-DD) | yes | Worldwide release date. |  |
| genre_id | string \| integer | yes | Root genre **code** (e.g. `electronic`) or legacy numeric id — see `GET /catalog/reference-data` → `genres_root` or the static tables below. |  |
| sub_genre_id | string \| integer |  | Subgenre **code** under the resolved root genre (see `subgenres_by_parent_code` in reference-data / docs bundle) or legacy numeric id. |  |
| album_type | string |  | Default Single. **Gard credits** (charged on successful submit, tied to your API key account): Single **500**, EP **700**, Album or Compilation **850**. | Single · EP · Album · Compilation |
| label | string |  | Label / imprint as shown on stores (P-line). ≤200 characters. |  |
| meta_lang | string |  | Metadata language: **ISO-style code** (e.g. en, ru) or a **language name / slug** resolvable from the languages list. | Code or name token; see static languages table. |
| sub_title | string |  | Album subtitle / version. |  |
| album_annotation | string |  | Short description / liner notes. |  |
| upc | string |  | Optional; max 14 digits. Leave empty for auto-assignment. |  |
| copyright | string |  | Optional. Your rights share on the composition, percent 0–100 (default 100). |  |
| platforms | string (JSON array) |  | Each entry: **platform code** (e.g. `spotify`) or legacy numeric id. Omit or empty → server may select all. |  |
| countries | string (JSON array) |  | Each entry: **territory code** (ISO `us`, `ru`, …) or legacy numeric id. Use `[]` for worldwide. See static countries table. |  |
| artist_roles | string (JSON array) | yes | Album-level credits: JSON array of `{ name, role, order? }`. **Required** — include at least one **`composer`** and one **`songwriter`** using real given + family names (same rule as the distributor web UI). |  |
| tracks_meta | string (JSON array) |  | One object per audio file in order. Fields include: name, version, isrc, track_po_code, author_rights, related_rights, explicit_content, is_cover, is_remix, is_instrumental, is_focus_track, is_live, is_drugs, preview_start, meta_lang, lyrics, persons (array of { name, role, order? }) — roles: artist, composer, songwriter (required) |  |
| sales_start_date | date string |  | Optional sales start. |  |
| preorder_date | date string |  | Optional pre-order date. |  |
| spotify_startsale_date | date string |  | Optional per-store date. |  |
| tiktok_startsale_date | date string |  | Optional. |  |
| yandex_startsale_date | date string |  | Optional. |  |
| oma_startsale_date | date string |  | Optional. |  |
| youtubered_upload_date | date string |  | Optional YouTube Music date. |  |
| itunes_cleared_for_stream | string bool |  | default true | true · false |
| itunes_not_cleared_for_sale | string bool |  | default false |  |
| is_single_maxi | string bool |  | default false |  |
| is_mixtape | string bool |  | default false |  |
| is_audio_book | string bool |  | default false |  |
| is_low_itunes_track_price | string bool |  | default false |  |
| itunes_has_mfit | string bool |  | default false |  |
| tiktok_ev | string bool |  | TikTok early video flag. default false |  |
| callback_url | string (URL) |  | Optional **your** HTTPS URL (any path). Same multipart `POST` as the release. Gard sends JSON with **`X-Gard-Signature: sha256=…`** (HMAC-SHA256 of the raw body). Verify using the **webhook signing secret** for the `gard_…` key (`GET /api/v1/keys/{id}/webhook-signing-secret`) or deployment `GARD_WEBHOOK_HMAC_SECRET` / `SECRET_KEY` for JWT-only submits. **HTTP 2xx**. |  |
| cover | file | yes | Cover image file (see media rules). |  |
| audio_files | file[] | yes | At least one audio file; field name can be repeated (multipart). |  |
| video | file |  | Optional video file. |  |
| booklet | file |  | Optional PDF booklet. |  |
| cover_url | string (URL) |  | Alternative to `cover`: public HTTP(S) URL to cover image. Max 50 MB. Use either `cover` or `cover_url`, not both. |  |
| audio_files_urls | string (JSON array) |  | Alternative to `audio_files`: JSON array of public HTTP(S) URLs. Must match `tracks_meta` count. Max 30 URLs, 50 MB each. Use either `audio_files` or `audio_files_urls`, not both. |  |
| video_url | string (URL) |  | Alternative to `video`: public HTTP(S) URL to video file. Max 50 MB. Use either `video` or `video_url`, not both. |  |
| booklet_url | string (URL) |  | Alternative to `booklet`: public HTTP(S) URL to PDF. Max 50 MB. Use either `booklet` or `booklet_url`, not both. |  |

#### Example request (illustrative JSON)

```json
{
  "release_name": "My Single",
  "artist_name": "Stage Name",
  "release_date": "2026-04-21",
  "genre_id": "electronic",
  "sub_genre_id": "ambient",
  "album_type": "Single",
  "label": "My Imprint",
  "meta_lang": "en",
  "platforms": ["spotify", "youtube_music", "apple_music"],
  "countries": [],
  "artist_roles": [
    { "name": "Stage Name", "role": "artist", "order": 1 },
    { "name": "Jane Q. Composer", "role": "composer", "order": 1 },
    { "name": "Jane Q. Composer", "role": "songwriter", "order": 1 }
  ],
  "tracks_meta": [
    {
      "name": "Track A",
      "meta_lang": "en",
      "persons": [
        { "name": "Stage Name", "role": "artist", "order": 1 },
        { "name": "Jane Q. Composer", "role": "composer", "order": 1 },
        { "name": "Jane Q. Composer", "role": "songwriter", "order": 1 }
      ]
    }
  ],
  "copyright": "100",
  "itunes_cleared_for_stream": "true",
  // BINARY upload (traditional):
  // "callback_url": "https://your-app.example/hooks/gard-moderation",
  "cover": "<binary JPEG/PNG file>",
  "audio_files": ["<binary WAV/FLAC/MP3>", "<optional second file>"]
  // OR URL-based upload (alternative — files downloaded server-side):
  // "cover_url": "https://example.com/cover.jpg",
  // "audio_files_urls": ["https://example.com/track1.wav", "https://example.com/track2.mp3"],
  // "video_url": "https://example.com/video.mov",
  // "booklet_url": "https://example.com/booklet.pdf",
  // NOTE: Use binary OR URL for each field — never both. URL files are deleted after upload.
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "msg": "Release submitted",
  "moderation_request_id": 42,
  "id": "mdr_01jqxyz",
  "release_id": null,
  "status": "submitted",
  "release_name": "My Single",
  "has_cover": true,
  "audio_count": 2,
  "has_video": false,
  "has_booklet": false
}
```

#### Example: cURL

```bash
# Cover & audio can be sent as binary parts (shown below) OR as public HTTP(S) URLs
# (use 'cover_url=…' / 'audio_files_urls=[…]'). Send EITHER binary OR URL per field — never both.
# 'artist_roles' must contain at least one 'composer' AND one 'songwriter' (same person OK).
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/moderation/" \
  -H "X-API-Key: $GARD_API_KEY" \
  -F release_name="My Single" \
  -F artist_name="Stage Name" \
  -F release_date="2026-04-21" \
  -F genre_id=electronic \
  -F sub_genre_id=ambient \
  -F meta_lang="en" \
  -F copyright="100" \
  -F platforms='["spotify","youtube_music","apple_music"]' \
  -F countries='[]' \
  -F artist_roles='[{"name":"Stage Name","role":"artist","order":1},{"name":"Jane Q. Composer","role":"composer","order":1},{"name":"Jane Q. Composer","role":"songwriter","order":1}]' \
  -F tracks_meta='[{"name":"Track A","meta_lang":"en","persons":[{"name":"Stage Name","role":"artist","order":1},{"name":"Jane Q. Composer","role":"composer","order":1},{"name":"Jane Q. Composer","role":"songwriter","order":1}]}]' \
  -F callback_url='https://your-app.example/hooks/gard-moderation' \
  -F cover=@./cover.jpg \
  -F audio_files=@./track1.wav

# URL-based alternative — drop the binary -F lines and use:
#   -F cover_url=https://example.com/cover.jpg \
#   -F audio_files_urls='["https://example.com/track1.wav"]'
```

#### Example: Python

```python
import os, json, requests

# Cover & audio can be sent as binary (files=...) OR as public HTTP(S) URLs (cover_url, audio_files_urls).
# Send EITHER binary OR URL per field — never both. Pick one and delete the other block below.
# 'artist_roles' must include at least one 'composer' AND one 'songwriter' (same person OK).
url = "https://back.gard-api.org" + "/api/v1/music-distributor/moderation/"
key = os.environ["GARD_API_KEY"]
data = {
    "release_name": "My Single",
    "artist_name": "Stage Name",
    "release_date": "2026-04-21",
    "genre_id": "electronic",
    "sub_genre_id": "ambient",
    "meta_lang": "en",
    "copyright": "100",
    "platforms": json.dumps(["spotify", "youtube_music", "apple_music"]),
    "countries": json.dumps([]),
    "artist_roles": json.dumps([
        {"name": "Stage Name", "role": "artist", "order": 1},
        {"name": "Jane Q. Composer", "role": "composer", "order": 1},
        {"name": "Jane Q. Composer", "role": "songwriter", "order": 1},
    ]),
    "tracks_meta": json.dumps([{
        "name": "Track A",
        "meta_lang": "en",
        "persons": [
            {"name": "Stage Name", "role": "artist", "order": 1},
            {"name": "Jane Q. Composer", "role": "composer", "order": 1},
            {"name": "Jane Q. Composer", "role": "songwriter", "order": 1},
        ],
    }]),
    "callback_url": "https://your-app.example/hooks/gard-moderation",
}

# (A) Binary upload — open real files (DO NOT pass empty placeholders, the server
#     now rejects 0-byte cover/audio parts with HTTP 400):
files = [
    ("cover", ("cover.jpg", open("cover.jpg", "rb"), "image/jpeg")),
    ("audio_files", ("t.wav", open("track1.wav", "rb"), "audio/wav")),
]
r = requests.post(url, headers={"X-API-Key": key}, data=data, files=files)

# (B) URL upload — comment out the 'files=' / requests.post above and use:
# data["cover_url"] = "https://example.com/cover.jpg"
# data["audio_files_urls"] = json.dumps(["https://example.com/track1.wav"])
# r = requests.post(url, headers={"X-API-Key": key}, data=data)

r.raise_for_status()
print(r.json())
```

#### Example: TypeScript

```typescript
// Cover & audio can be sent as binary parts (shown below) OR as public HTTP(S) URLs
// (cover_url, audio_files_urls). Send EITHER binary OR URL per field — never both.
// 'artist_roles' must contain at least one 'composer' AND one 'songwriter' (same person OK).
// IMPORTANT: do not call `fd.append("cover", new Blob([]), "cover.jpg")` — an empty
// part is now rejected with HTTP 400. Pass a real File / Blob, or omit the field
// entirely and use `cover_url` instead.
const fd = new FormData();
fd.append("release_name", "My Single");
fd.append("artist_name", "Stage Name");
fd.append("release_date", "2026-04-21");
fd.append("genre_id", "electronic");
fd.append("sub_genre_id", "ambient");
fd.append("meta_lang", "en");
fd.append("copyright", "100");
fd.append("platforms", JSON.stringify(["spotify", "youtube_music", "apple_music"]));
fd.append("countries", JSON.stringify([]));
fd.append("artist_roles", JSON.stringify([
  { name: "Stage Name", role: "artist", order: 1 },
  { name: "Jane Q. Composer", role: "composer", order: 1 },
  { name: "Jane Q. Composer", role: "songwriter", order: 1 },
]));
fd.append("tracks_meta", JSON.stringify([{
  name: "Track A", meta_lang: "en",
  persons: [
    { name: "Stage Name", role: "artist", order: 1 },
    { name: "Jane Q. Composer", role: "composer", order: 1 },
    { name: "Jane Q. Composer", role: "songwriter", order: 1 },
  ],
}]));
fd.append("callback_url", "https://your-app.example/hooks/gard-moderation");

// (A) Binary upload — coverFile / trackFile are real File objects from
//     <input type="file"> (or any Blob whose size > 0):
fd.append("cover", coverFile, coverFile.name);
fd.append("audio_files", trackFile, trackFile.name);

// (B) URL-based upload — DO NOT append the binary fields above; instead:
// fd.append("cover_url", "https://example.com/cover.jpg");
// fd.append("audio_files_urls", JSON.stringify(["https://example.com/track1.wav"]));

const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/moderation/`, {
  method: "POST",
  headers: { "X-API-Key": process.env.GARD_API_KEY! },
  body: fd,
});
if (!r.ok) throw new Error(await r.text());
console.log(await r.json());
```


## GET `/api/v1/music-distributor/moderation/`

List submissions: `{ code, msg, submissions: [...] }`. Each row: `status` + human `message` (vendor-neutral).

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "msg": "ok",
  "submissions": [
    {
      "moderation_request_id": 42,
      "id": "mdr_01jqxyz",
      "release_id": 128,
      "status": "submitted",
      "message": "Release submitted",
      "release_name": "My Single",
      "artist_name": "Stage Name",
      "created_at": "2026-04-21T10:00:00Z"
    }
  ]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/moderation/" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
r = requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/moderation/",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
)
r.raise_for_status()
print(r.json())
```

#### Example: TypeScript

```typescript
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/moderation/`, {
  headers: { "X-API-Key": process.env.GARD_API_KEY! },
});
if (!r.ok) throw new Error(await r.text());
console.log(await r.json());
```


## GET `/api/v1/music-distributor/catalog/reference-data`

One JSON snapshot: **platforms**, **countries**, **languages**, **genres_root** (each `{code, name}`), **subgenres_by_parent_code** (root genre code → subgenres), and optional **live_supplement** (platform groups, lines, price categories). Send **`X-API-Key: gard_…`**. You can cache this response in your integration.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "platforms": [{ "code": "spotify", "name": "Spotify" }],
  "countries": [{ "code": "ru", "name": "Russian Federation" }],
  "languages": [{ "code": "en", "name": "English" }],
  "genres_root": [{ "code": "electronic", "name": "Electronic" }],
  "subgenres_by_parent_code": {
    "electronic": [
      { "code": "ambient", "name": "Ambient" },
      { "code": "bass", "name": "Bass" }
    ]
  },
  "live_supplement": {
    "platform_groups": [],
    "lines": [],
    "price_categories": []
  }
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/catalog/reference-data" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
r = requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/catalog/reference-data",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
)
r.raise_for_status()
print(r.json())
```

#### Example: TypeScript

```typescript
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/catalog/reference-data`, {
  headers: { "X-API-Key": process.env.GARD_API_KEY! },
});
console.log(await r.json());
```


## GET `/api/v1/music-distributor/catalog/platforms`

List DSP **platforms** as `{id, name, platform_name}` from the live catalog cache. Prefer **`GET /catalog/reference-data`** for `{code, name}` rows aligned with **`POST /moderation/`** (`platforms` field). Same auth as other catalog routes.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
[{ "id": 1, "name": "Spotify", "platform_name": "Spotify" }]
```


## GET `/api/v1/music-distributor/catalog/platform-groups`

Platform groupings from cache (for UI filters). **`reference-data`** may also include **`live_supplement.platform_groups`**.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
[]
```


## GET `/api/v1/music-distributor/releases/all`

List releases in your catalog. Optional `search`, `offset`, `limit`. Each row includes **`release_id`** (numeric catalog id for `GET …/releases/{release_ref}/status`), **`id`** / **`public_id`** (`rel_…`), **`status`** / **`message`** (public workflow — same vocabulary as **`GET /moderation/`**), plus metadata. **`admin`** users may see extra read-only fields (`internal_catalog_status`, `upstream_album_id`).

#### Example request (illustrative JSON)

```json
{
  "search": "summer",
  "offset": 0,
  "limit": 50
}
```

#### Example response (illustrative JSON)

```json
[
    {
      "id": "rel_01abc",
      "public_id": "rel_01abc",
      "release_id": 123,
      "name": "Summer EP",
      "type": "EP",
      "status": "under_review",
      "message": "Under moderation review",
      "upc": "886447833821",
      "artist_name": "Stage Name",
      "label": "Indie",
      "genre_name": "Electronic",
      "sale_platforms": [],
      "has_cover": true,
      "comment": null,
      "release_date": "2026-06-01",
      "last_synced_at": "2026-04-21T11:00:00",
      "created_at": "2026-04-20T09:00:00"
    }
  ]
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/releases/all?search=label&offset=0&limit=50" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
r = requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/releases/all",
    params={"search": "my label", "offset": 0, "limit": 50},
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
)
r.raise_for_status()
print(r.json())
```

#### Example: TypeScript

```typescript
const u = new URL("/api/v1/music-distributor/releases/all", "https://back.gard-api.org");
u.searchParams.set("search", "my label");
u.searchParams.set("offset", "0");
u.searchParams.set("limit", "50");
const r = await fetch(u, { headers: { "X-API-Key": process.env.GARD_API_KEY! } });
console.log(await r.json());
```


## GET `/api/v1/music-distributor/releases/{release_ref}`

Get one release. **`{release_ref}`** may be: numeric **`release_id`**, catalog **`rel_…`**, or moderation submission **`mdr_…`** (same resolution rules as **GET …/status**). **`status`** / **`message`** are the public workflow. Raw distributor fields (`upstream_status_data`, `upstream_album_id`, `internal_catalog_status`) are returned **only** for **`admin`**.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "id": 123,
  "public_id": "rel_01abc",
  "name": "Summer EP",
  "type": "EP",
  "status": "under_review",
  "message": "Under moderation review",
  "metadata": null,
  "upc": "886447833821",
  "artist_name": "Stage Name",
  "label": "Indie",
  "genre_name": "Electronic",
  "sale_platforms": [],
  "has_cover": true,
  "comment": null,
  "release_date": "2026-06-01",
  "last_synced_at": "2026-04-21T11:00:00",
  "tracks": [
    { "track_id": "track_01abc", "position": 1, "title": "Intro", "isrc": "QZ-ES5-26-00001" }
  ]
}
```


## GET `/api/v1/music-distributor/releases/{release_ref}/status`

Live distributor snapshot for the release. Path **`{release_ref}`** accepts: **(1)** numeric catalog **`release_id`** (`md_releases.id`, also returned as **`id`** in this response and in **`GET /releases/all`** as **`release_id`**), **(2)** catalog **`rel_…`**, **(3)** moderation **`mdr_…`** (your **`POST /moderation/`** `id`; resolves to the linked catalog row, then calls the distributor with the stored upstream album id).

**`status`** / **`message`** match **`GET /moderation/`** and webhooks. **`tracks`** includes **`track_id`** (`track_…`) per row — same as **`GET …/tracks`**; use in **`POST /analytics/releases`**. Before delivery **`track_id`** may be **`null`**. **`tracks_isrc`** kept for backward compatibility. Admin-only: **`internal_catalog_status`**, **`upstream_album_id`**. **`GET`** and **`POST …/sync`** return the same JSON.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "id": 123,
  "public_id": "rel_01abc",
  "status": "submitted",
  "message": "Release submitted",
  "name": "My Single",
  "artist_name": "Stage Name",
  "album_type": "Single",
  "moderation_request_id": 42,
  "submission_id": "mdr_01jqxyz",
  "upc": "886447833821",
  "release_date": "2026-06-01",
  "label": "Indie",
  "genre_name": "Electronic",
  "sale_platforms": [],
  "has_cover": true,
  "comment": null,
  "last_synced_at": "2026-04-21T11:30:00",
  "tracks": [
    { "track_id": "track_01abc", "position": 1, "title": "Intro", "isrc": "QZ-ES5-26-00001" },
    { "track_id": "track_01def", "position": 2, "title": "Outro", "isrc": "QZ-ES5-26-00002" }
  ]
}
```


## POST `/api/v1/music-distributor/releases/{release_ref}/sync`

Re-fetch status and metadata (same as GET …/status). **`{release_ref}`** accepts numeric id, **`rel_…`**, or **`mdr_…`**.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "id": 123,
  "public_id": "rel_01abc",
  "status": "under_review",
  "message": "Under moderation review",
  "name": "Summer EP",
  "artist_name": "Stage Name",
  "album_type": "EP",
  "moderation_request_id": 42,
  "submission_id": "mdr_01jqxyz",
  "upc": "886447833821",
  "release_date": "2026-06-01",
  "label": "Indie",
  "genre_name": "Electronic",
  "sale_platforms": [],
  "has_cover": true,
  "comment": null,
  "last_synced_at": "2026-04-21T11:31:00"
}
```


## GET `/api/v1/music-distributor/releases/{release_ref}/cover`

Binary cover art. **`{release_ref}`**: numeric id, **`rel_…`**, or **`mdr_…`**.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "note": "Response body is raw image bytes (JPEG or PNG), not JSON. Content-Type is typically image/jpeg or image/png.",
  "example_content_type": "image/jpeg",
  "example_content_length": 245678
}
```


## GET `/api/v1/music-distributor/releases/persons/search?query=…`

Search people in the distributor directory (for credits).

#### Example request (illustrative JSON)

```json
{
  "query": "Artist"
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "results": [
    { "id": 55, "content_name": "Artist Name", "match_score": 0.98 }
  ]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/releases/persons/search?query=Artist" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
r = requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/releases/persons/search",
    params={"query": "Artist"},
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
)
r.raise_for_status()
print(r.json())
```

#### Example: TypeScript

```typescript
const u = new URL("/api/v1/music-distributor/releases/persons/search", "https://back.gard-api.org");
u.searchParams.set("query", "Artist");
const r = await fetch(u, { headers: { "X-API-Key": process.env.GARD_API_KEY! } });
console.log(await r.json());
```


## POST `/api/v1/music-distributor/releases/persons`

Body: { content_name: string }. Create a person entry.

#### Example request (illustrative JSON)

```json
{
  "content_name": "New Artist"
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "person": { "id": 901, "content_name": "New Artist" }
}
```

#### Example: cURL

```bash
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/releases/persons" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content_name":"New Artist"}'
```

#### Example: Python

```python
import os, requests
r = requests.post(
    "https://back.gard-api.org" + "/api/v1/music-distributor/releases/persons",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
    json={"content_name": "New Artist"},
)
r.raise_for_status()
print(r.json())
```

#### Example: TypeScript

```typescript
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/releases/persons`, {
  method: "POST",
  headers: {
    "X-API-Key": process.env.GARD_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ content_name: "New Artist" }),
});
console.log(await r.json());
```


## GET `/api/v1/music-distributor/releases/{release_ref}/video-clips`

Album video clips list.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "clips": [
    { "id": 1, "title": "Official video", "url": "https://cdn.example.com/clip1.mp4", "track_id": null }
  ]
}
```


## GET `/api/v1/music-distributor/releases/{release_ref}/track-video-clips`

Per-track video clips.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "clips": [
    { "id": 2, "track_id": 1, "title": "Vertical clip", "url": "https://cdn.example.com/t1_clip.mp4" }
  ]
}
```


## GET `/api/v1/music-distributor/releases/{release_ref}/persons`

Album person links.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "persons": [
    { "person_id": 55, "role": "artist", "order": 1, "name": "Stage Name" }
  ]
}
```


## POST `/api/v1/music-distributor/releases/{release_ref}/persons`

Add album person (body per backend).

#### Example request (illustrative JSON)

```json
{
  "person_id": 55,
  "order": 1,
  "role": "artist"
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "link": { "release_id": 123, "person_id": 55, "role": "artist", "order": 1 }
}
```


## GET `/api/v1/music-distributor/releases/{release_ref}/track-persons`

Track person links.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "track_persons": [
    { "track_id": 1, "person_id": 55, "role": "artist", "order": 1 }
  ]
}
```


## POST `/api/v1/music-distributor/releases/{release_ref}/track-persons`

Add track person.

#### Example request (illustrative JSON)

```json
{
  "track_id": 1,
  "person_id": 55,
  "order": 1,
  "role": "featured_artist"
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "link": { "track_id": 1, "person_id": 55, "role": "featured_artist", "order": 1 }
}
```


## POST `/api/v1/music-distributor/releases/{release_ref}/sort-tracks`

Reorder tracks (body per backend).

#### Example request (illustrative JSON)

```json
{
  "track_ids": [3, 1, 2]
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "msg": "order updated"
}
```


## GET `/api/v1/music-distributor/releases/{release_ref}/platform-links`

DSP storefront links. Returns **sale_platforms** as **{ platform_name, link }** for all available platforms: **Wink**, **MTS**, **Yandex Music**, **Spotify**, **VK Music**, **Zvuk**.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "id": 123,
  "public_id": "rel_01abc",
  "name": "Summer EP",
  "upc": "886447833821",
  "platforms": [
    { "platform_name": "Wink", "link": "https://music.wink.ru/release/xxxxxxxxxxx" },
    { "platform_name": "Yandex Music", "link": "https://music.yandex.ru/album/xxxxxxxxxxx" },
    { "platform_name": "Spotify", "link": "https://open.spotify.com/album/xxxxxxxxxxx" },
    { "platform_name": "MTS", "link": "https://music.mts.ru/album/xxxxxxxxxxx" },
    { "platform_name": "VK Music", "link": "https://music.vk.com/link/xxxxxxxxxxx" },
    { "platform_name": "Zvuk", "link": "https://zvuk.com/release/xxxxxxxxxxx" }
  ]
}
```


## POST `/api/v1/music-distributor/releases/{release_ref}/revoke`

Distributor **platform moderation** withdraw or catalog drop: if the live upstream snapshot maps to internal **`under_review`** (staff/platform review, `can_revoke` + `comment_time`, codes 1/5, `moderation` / `onedit`), calls upstream **revoke** and sets the catalog row to **draft**. If not, **only removes your Gard catalog row** (same as `DELETE …/releases/{release_ref}` — no upstream revoke). **400** if the release is already **`live`** — use `POST /delete-requests/` instead.

Alternate success body when **not** on distributor moderation: `{"status":"deleted","release_id":128,"upstream_album_id":95501}` (catalog row removed only). **400** when workflow is **`live`**.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "status": "revoked",
  "release_id": 128,
  "upstream_album_id": 95501
}
```


## POST `/api/v1/music-distributor/delete-requests/`

Takedown queue for releases **already live** on DSPs. **Only accepted when the catalog row’s public `status` is `live`** (same rules as `GET /releases/{release_ref}`); otherwise **400** with the current status — use `POST …/revoke` or `DELETE …/releases/{release_ref}` for pre-live catalog/moderation handling. The request is processed by the Gard team — poll `GET /delete-requests/`.

### Request fields

| Field | Type | Required | Description | Options |
| --- | --- | --- | --- | --- |
| release_id | string | yes | Opaque public_id of the release. |  |
| release_name | string |  | For display. |  |
| artist_name | string |  | For display. |  |
| upc | string |  | Optional. |  |
| isrc | string |  | Optional. |  |
| reason | string |  | Takedown reason. |  |

#### Example request (illustrative JSON)

```json
{
  "release_id": "rel_01abc",
  "release_name": "Summer EP",
  "artist_name": "Stage Name",
  "upc": "886447833821",
  "reason": "Artist requested takedown"
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "id": 501,
  "status": "pending"
}
```

#### Example: cURL

```bash
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/delete-requests/" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"release_id":"rel_xxxxxxxx","reason":"Artist request"}'
```

#### Example: Python

```python
import os, requests
r = requests.post(
    "https://back.gard-api.org" + "/api/v1/music-distributor/delete-requests/",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
    json={"release_id": "rel_xxxxxxxx", "reason": "Artist request"},
)
print(r.json())
```

#### Example: TypeScript

```typescript
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/delete-requests/`, {
  method: "POST",
  headers: { "X-API-Key": process.env.GARD_API_KEY!, "Content-Type": "application/json" },
  body: JSON.stringify({ release_id: "rel_xxxxxxxx", reason: "Artist request" }),
});
console.log(await r.json());
```


## GET `/api/v1/music-distributor/delete-requests/`

List all takedown requests you have submitted. Status: pending → completed → rejected.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "requests": [
    {
      "id": 501,
      "release_id": "rel_01abc",
      "status": "pending",
      "reason": "Artist requested takedown",
      "created_at": "2026-04-20T09:00:00Z"
    }
  ]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/delete-requests/" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/delete-requests/",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/api/v1/music-distributor/delete-requests/`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## GET `/api/v1/music-distributor/panel/scope`

Dashboard: artists + releases in your scope. Each release includes **`release_id`** (numeric catalog id), **`status`** / **`message`** (public workflow), and optional **`admin`**-only debug fields.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "artists": ["Stage Name"],
  "releases": [
    {
      "id": "rel_01abc",
      "public_id": "rel_01abc",
      "release_id": 123,
      "name": "Summer EP",
      "artist_name": "Stage Name",
      "status": "under_review",
      "message": "Under moderation review",
      "upc": "886447833821",
      "release_date": "2026-06-01"
    }
  ]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/panel/scope" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/panel/scope",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/api/v1/music-distributor/panel/scope`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## GET `/api/v1/music-distributor/panel/activity-log`

Aggregated activity. Query: artist, action, limit, offset.

#### Example request (illustrative JSON)

```json
{
  "artist": "Stage Name",
  "action": "submit",
  "limit": 20,
  "offset": 0
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "events": [
    {
      "id": 1001,
      "action": "submit",
      "entity_type": "release",
      "entity_id": "rel_01abc",
      "created_at": "2026-04-21T08:00:00Z"
    }
  ],
  "total": 42
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/panel/activity-log?limit=20&offset=0" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/panel/activity-log",
    params={"limit": 20, "offset": 0},
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
const u = new URL("/api/v1/music-distributor/panel/activity-log", "https://back.gard-api.org");
u.searchParams.set("limit", "20");
const r = await fetch(u, { headers: { "X-API-Key": process.env.GARD_API_KEY! } });
console.log(await r.json());
```


## GET `/api/v1/music-distributor/panel/reports/streaming.csv`

CSV export of your releases (400 if none).

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "note": "Response body is text/csv, not JSON. HTTP 400 if there is no data to export.",
  "example_csv_first_lines": "upc,title,streams\n886447833821,Summer EP,125000\n"
}
```

#### Example: cURL

```bash
curl -sS -o report.csv "https://back.gard-api.org/api/v1/music-distributor/panel/reports/streaming.csv" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
r = requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/panel/reports/streaming.csv",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
)
open("report.csv", "w", encoding="utf-8").write(r.text)
```

#### Example: TypeScript

```typescript
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/panel/reports/streaming.csv`, {
  headers: { "X-API-Key": process.env.GARD_API_KEY! },
});
console.log(await r.text());
```


## POST `/api/v1/music-distributor/pitch/`

Editorial pitch while the release is **not yet `live`** in the public workflow (same status resolution as `GET /moderation/`). Multipart + `payload_json` string. **400** once **`live`**.

**50 credits** per request (402 if insufficient). `pitch_platforms`: yandex_music, vk_music, zvooq, amazon_music, spotify, apple_music — allowed until public **`live`** (including `sent_to_stores` / delivery phases).

### Request fields

| Field | Type | Required | Description | Options |
| --- | --- | --- | --- | --- |
| moderation_request_id | integer | yes | Id of the moderation submission this pitch is tied to (from your product / support workflow). |  |
| payload_json | string (JSON in form) | yes | release_description, artist_bio_achievements, pitch_platforms[] |  |
| artist_photo | file |  | Optional; max 15 MB; jpg/png/webp. |  |

#### Example request (illustrative JSON)

```json
{
  "_wire_format": "multipart/form-data",
  "moderation_request_id": "42",
  "payload_json": "<one form field: JSON.stringify of the object below>",
  "payload": {
    "release_description": "…",
    "artist_bio_achievements": "…",
    "pitch_platforms": ["spotify", "apple_music"]
  },
  "artist_photo": "<optional binary>"
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "id": 77,
  "status": "received"
}
```

#### Example: cURL

```bash
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/pitch/" \
  -H "X-API-Key: $GARD_API_KEY" \
  -F moderation_request_id=1 \
  -F payload_json='{"release_description":"…","artist_bio_achievements":"…","pitch_platforms":["spotify"]}'
```

#### Example: Python

```python
import os, requests
url = "https://back.gard-api.org" + "/api/v1/music-distributor/pitch/"
data = {
    "moderation_request_id": "1",
    "payload_json": '{"release_description":"x","artist_bio_achievements":"y","pitch_platforms":["spotify"]}',
}
r = requests.post(url, headers={"X-API-Key": os.environ["GARD_API_KEY"]}, data=data)
print(r.json())
```

#### Example: TypeScript

```typescript
const fd = new FormData();
fd.append("moderation_request_id", "1");
fd.append("payload_json", JSON.stringify({
  release_description: "…",
  artist_bio_achievements: "…",
  pitch_platforms: ["spotify"],
}));
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/pitch/`, {
  method: "POST",
  headers: { "X-API-Key": process.env.GARD_API_KEY! },
  body: fd,
});
console.log(await r.json());
```


## GET `/api/v1/music-distributor/pitch/`

List your pitch requests (all statuses: pending, in_progress, completed, rejected).

Integrators must read **`pitches`** from this object (not a bare JSON array). Staff actions in the Gard panel set **`completed`**, **`rejected`**, or **`in_progress`**; those rows remain visible here.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "msg": "OK",
  "pitches": [
    {
      "id": 78,
      "moderation_request_id": 42,
      "status": "completed",
      "pitch_platforms": ["spotify", "apple_music"],
      "created_at": "2026-04-19T12:00:00Z",
      "updated_at": "2026-04-21T09:30:00Z",
      "reviewer_notes": null
    },
    {
      "id": 77,
      "moderation_request_id": 41,
      "status": "pending",
      "pitch_platforms": ["yandex_music"],
      "created_at": "2026-04-18T10:00:00Z",
      "updated_at": "2026-04-18T10:00:00Z",
      "reviewer_notes": null
    }
  ]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/pitch/" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/pitch/",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/api/v1/music-distributor/pitch/`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## GET `/api/v1/music-distributor/payout/settings`

Payout method + details.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "method": "paypal",
  "details": { "paypal_email": "you@example.com" }
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/payout/settings" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/payout/settings",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/api/v1/music-distributor/payout/settings`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## PUT `/api/v1/music-distributor/payout/settings`

Set payout. JSON: { method: paypal|bank_account|card_swift|card_ru, details?: { … } }.

#### Example request (illustrative JSON)

```json
{
  "method": "paypal",
  "details": { "paypal_email": "you@example.com" }
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "msg": "settings saved"
}
```

#### Example: cURL

```bash
curl -sS -X PUT "https://back.gard-api.org/api/v1/music-distributor/payout/settings" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"method":"paypal","details":{"paypal_email":"you@example.com"}}'
```

#### Example: Python

```python
import os, requests
r = requests.put(
    "https://back.gard-api.org" + "/api/v1/music-distributor/payout/settings",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
    json={"method": "paypal", "details": {"paypal_email": "you@example.com"}},
)
print(r.json())
```

#### Example: TypeScript

```typescript
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/payout/settings`, {
  method: "PUT",
  headers: { "X-API-Key": process.env.GARD_API_KEY!, "Content-Type": "application/json" },
  body: JSON.stringify({ method: "paypal", details: { paypal_email: "you@example.com" } }),
});
console.log(await r.json());
```


## GET `/api/v1/music-distributor/payout/withdrawals`

List withdrawals (query limit).

#### Example request (illustrative JSON)

```json
{
  "limit": 50
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "withdrawals": [
    {
      "id": 9001,
      "amount_cents": 5000,
      "currency": "USD",
      "status": "completed",
      "created_at": "2026-04-01T00:00:00Z"
    }
  ]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/payout/withdrawals?limit=50" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/payout/withdrawals",
    params={"limit": 50},
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
const u = new URL("/api/v1/music-distributor/payout/withdrawals", "https://back.gard-api.org");
u.searchParams.set("limit", "50");
console.log(await (await fetch(u, { headers: { "X-API-Key": process.env.GARD_API_KEY! } })).json());
```


## POST `/api/v1/music-distributor/payout/withdrawals/request`

Request a withdrawal. JSON: { amount_cents, currency } — min 100 cents.

#### Example request (illustrative JSON)

```json
{
  "amount_cents": 5000,
  "currency": "USD"
}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "withdrawal_id": 9002,
  "status": "pending"
}
```

#### Example: cURL

```bash
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/payout/withdrawals/request" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount_cents":5000,"currency":"USD"}'
```

#### Example: Python

```python
import os, requests
r = requests.post(
    "https://back.gard-api.org" + "/api/v1/music-distributor/payout/withdrawals/request",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
    json={"amount_cents": 5000, "currency": "USD"},
)
print(r.json())
```

#### Example: TypeScript

```typescript
const r = await fetch(`https://back.gard-api.org/api/v1/music-distributor/payout/withdrawals/request`, {
  method: "POST",
  headers: { "X-API-Key": process.env.GARD_API_KEY!, "Content-Type": "application/json" },
  body: JSON.stringify({ amount_cents: 5000, currency: "USD" }),
});
console.log(await r.json());
```


## POST `/api/v1/music-distributor/analytics/releases`

★ Recommended. Batch analytics for up to 100 releases (rel_… and/or mdr_… — mix allowed) in one request. Returns per-release totals, per-platform streams, and per-track (ISRC) breakdowns for the chosen period. Served from the daily report (md_analytics_stream_facts) — no live upstream call.

**One call, many releases.** Each `ref` is ownership-checked independently — refs you don't own (or that don't exist) come back as `{found:false, error:"not_found_or_forbidden"}` instead of leaking data. **Period:** use `preset` (last_1d / last_7d / last_28d / last_30d / last_90d) or `custom` with `from`+`to` — there is no `today` (analytics exist only for previous days). `last_*` windows end at the latest fully-ingested day (**today − 2**, because analytics are collected nightly at 00:00 for the day-before-previous). **Secondary breakdowns** (`devices`, `os`, `age`, `gender`, `timeseries`) are **off by default** — switch on only what you need. **Release roll-ups aggregate every track of the release by UPC; per-track rows are keyed by ISRC.** All platforms present in the daily report are returned automatically (no fixed list). Use the **`rel_…`** id from **GET /releases/all** or the **`mdr_…`** id from your submission. For single-release convenience there is also **GET /analytics/release/{ref}** and **GET /analytics/track/{track_ref}**.

### Request fields

| Field | Type | Required | Description | Options |
| --- | --- | --- | --- | --- |
| releases | string[] | yes | 1–100 release ids. Each may be a release public id (rel_…) or a moderation/submission public id (mdr_…). Mixed lists are allowed; duplicates are de-duplicated. Ids you do not own are returned with found:false (never another tenant's data). |  |
| period.preset | string |  | Reporting window. One of: last_1d, last_7d, last_28d, last_30d, last_90d, custom. Default: last_28d. There is no 'today' — analytics are only available for previous days; last_* windows end on the latest fully-ingested day (today − 2). | last_1d \| last_7d \| last_28d \| last_30d \| last_90d \| custom |
| period.from / period.to | string (YYYY-MM-DD) |  | Required only when preset = custom. Inclusive date range. |  |
| include.platforms | boolean |  | Per-platform stream/paid breakdown (release + per track). Default: true. |  |
| include.countries | boolean |  | Per-country breakdown (release + per track). Default: true. |  |
| include.tracks | boolean |  | Per-track rows with track_id, isrc, title, streams and paid streams (and per-track by_platform/by_country when those toggles are on). Always true — omit include or set false; the API still returns tracks. |  |
| include.devices / include.os / include.age / include.gender | boolean |  | Optional secondary demographic/technical breakdowns (yes/no). Default: false — turn on only what you need to keep responses small. |  |
| include.timeseries | boolean |  | Per-day stream/paid series for each release. Default: false. |  |

#### Example request (illustrative JSON)

```json
// Last 28 days, default breakdowns (platforms + countries + tracks):
{
  "releases": ["rel_ExampleId123", "mdr_ExampleSubmission9"],
  "period": { "preset": "last_28d" }
}

// One day, with demographic breakdowns turned on:
{
  "releases": ["rel_ExampleId123"],
  "period": { "preset": "last_1d" },
  "include": {
    "platforms": true,
    "countries": true,
    "tracks": true,
    "devices": true,
    "age": true,
    "gender": true,
    "timeseries": false
  }
}

// Custom date range:
{
  "releases": ["rel_ExampleId123", "rel_ExampleId456"],
  "period": { "preset": "custom", "from": "2026-05-01", "to": "2026-05-29" },
  "include": { "platforms": true, "countries": false, "tracks": true }
}
```

#### Example response (illustrative JSON)

```json
{
  "period": { "preset": "last_28d", "from": "2026-05-02", "to": "2026-05-29" },
  "include": { "platforms": true, "countries": true, "tracks": true, "devices": false, "os": false, "age": false, "gender": false, "timeseries": false },
  "requested": 2,
  "found": 1,
  "releases": [
    {
      "ref": "rel_ExampleId123",
      "found": true,
      "release": {
        "public_id": "rel_ExampleId123",
        "name": "Sunset Stories",
        "artist": "Aurora Nightingale",
        "upc": "5060000000001"
      },
      "totals": { "streams": 18452, "pay_streams": 9120 },
      "by_platform": [
        { "name": "VKontakte",     "streams": 15230, "pay_streams": 7610 },
        { "name": "Spotify",       "streams": 1180,  "pay_streams": 720 },
        { "name": "Yandex Music",  "streams": 760,   "pay_streams": 410 },
        { "name": "Apple Music",   "streams": 540,   "pay_streams": 300 },
        { "name": "Zvuk",          "streams": 300,   "pay_streams": 150 },
        { "name": "MTS Music",     "streams": 180,   "pay_streams": 70 },
        { "name": "Deezer",        "streams": 120,   "pay_streams": 30 },
        { "name": "YouTube Music", "streams": 80,    "pay_streams": 20 },
        { "name": "Amazon Music",  "streams": 42,    "pay_streams": 10 },
        { "name": "Tidal",         "streams": 20,    "pay_streams": 0 }
      ],
      "by_country": [
        { "name": "Russia",     "streams": 16110, "pay_streams": 8020 },
        { "name": "Belarus",    "streams": 720,   "pay_streams": 360 },
        { "name": "Kazakhstan", "streams": 540,   "pay_streams": 250 }
      ],
      "tracks": [
        {
          "track_id": "track_ExampleTrackA",
          "isrc": "QZ-ABC-26-00001",
          "title": "Sunset Stories",
          "streams": 12010,
          "pay_streams": 6300,
          "by_platform": [
            { "name": "VKontakte", "streams": 9900, "pay_streams": 5200 },
            { "name": "Spotify",   "streams": 820,  "pay_streams": 510 }
          ],
          "by_country": [
            { "name": "Russia",  "streams": 10800, "pay_streams": 5600 },
            { "name": "Belarus", "streams": 410,   "pay_streams": 220 }
          ]
        },
        {
          "track_id": "track_ExampleTrackB",
          "isrc": "QZ-ABC-26-00002",
          "title": "Afterglow",
          "streams": 6442,
          "pay_streams": 2820,
          "by_platform": [
            { "name": "VKontakte", "streams": 5330, "pay_streams": 2410 }
          ],
          "by_country": [
            { "name": "Russia", "streams": 5310, "pay_streams": 2420 }
          ]
        }
      ]
    },
    {
      "ref": "mdr_ExampleSubmission9",
      "found": false,
      "error": "not_found_or_forbidden"
    }
  ]
}
```


## GET `/api/v1/music-distributor/analytics/summary/filters`

Analytics filter metadata (catalog-scoped).

Analytics: **one HTTP call = one report** — there is no single endpoint that returns summary + every DSP together. For each slice (summary table, Spotify graph, Yandex graph, …) call the matching URL. Gard serves responses from its own Postgres database — see response header **X-Gard-Analytics-Cached** (`true` = snapshot, `facts` = per-album aggregation). Full contract: **`docs/music-distributor.md`** (Analytics).

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "code": 200,
  "date_ranges": ["last_7d", "last_28d", "last_90d"],
  "metrics": ["streams", "listeners"],
  "albums": [{ "catalog_album_id": "ca_1", "title": "Summer EP" }]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/filters" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/api/v1/music-distributor/analytics/summary/filters",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/api/v1/music-distributor/analytics/summary/filters`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## POST `/api/v1/music-distributor/analytics/summary/table`

Cross-store **table** (all DSPs combined in this upstream view). Minimal POST body; Gard adds date range and Cabinet **custom_filters** from your catalog.

**Request:** `{"filters":{}}` is enough (Gard sets `from`/`to` when omitted). **All analytics POST endpoints share the same filter shape** — same keys work for `summary/*`, `spotify/*`, `yandex/*`, `applemusic/*`, `vkclips/*`, `umavk/*`, `mts/*`, `zvooq/*`. **Narrow by:** `filters.release_public_ids: ["rel_…"]` — use the **`rel_…`** id from **GET /releases/all** (not `mdr_…`). Also: `filters.album_ids: [38588899]`, `filters.artist_names: ["Aurora Nightingale"]`. Combine to take the union. Pass `from`/`to` (ISO dates) for any custom range — Gard aggregates per-day facts from its own Postgres (no live upstream call). Legacy back-compat: top-level `gard_release_public_id` / `gard_analytics_album_ids` / `gard_artist_names`. **Unknown id → 400** (no silent widening). **No data yet → 503** with `Retry-After: 30` — Gard schedules a background fill so the next call lands. **Response:** table payloads use **`pages`**, **`data`**.

#### Example request (illustrative JSON)

```json
// Whole catalog (default 31-day window):
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}

// By artist + custom date range:
{
  "filters": { "artist_names": ["Aurora Nightingale"] },
  "from": "2026-04-01",
  "to": "2026-04-30"
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["cover", "track", "artist", "album", "country", "streams", "pay_streams"],
  "data": [
    {
      "track": "Sample Track Name",
      "artist": "Aurora Nightingale",
      "album": "Sunset Stories",
      "album_id": 38588899,
      "country": "ru",
      "streams": 49,
      "pay_streams": 47
    }
  ],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog (default 31-day window):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/table"

# Whole catalog:
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/spotify/table`

Spotify analytics table (JSON body). Same minimal POST contract as summary analytics.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}

// Custom date range:
{
  "filters": {},
  "from": "2026-04-01",
  "to": "2026-04-30"
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["track", "isrc", "streams"],
  "data": [{ "track": "Track A", "isrc": "USXXX2400001", "streams": 80000 }],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/table"

# Whole catalog:
print(requests.post(url, headers={"X-API-Key": key}, json={"filters": {}}).json())

# One release:
print(requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
}).json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/applemusic/table`

Apple Music analytics table.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["album", "plays"],
  "data": [{ "album": "Summer EP", "plays": 60000 }],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/table"

# Whole catalog:
print(requests.post(url, headers={"X-API-Key": key}, json={"filters": {}}).json())

# One release:
print(requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
}).json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());
```


## GET `/api/v1/music-distributor/analytics/spotify/filters`

Spotify analytics filter metadata (catalog-scoped). Same prerequisite as other analytics routes.

Analytics: **400** if you have no synced releases with upstream album ids. Responses are narrowed to your catalog.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "filters": { "date_range": ["last_7d", "last_28d"] },
  "dimensions": ["track", "album"],
  "metrics": ["streams"]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/filters" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/analytics/spotify/filters",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/analytics/spotify/filters`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## POST `/api/v1/music-distributor/analytics/spotify/graph`

Spotify — daily time-series graph.

**Graph-style** responses expose **`lines`** (metric keys) and **`data`** (points; **`name`** is usually an ISO date). Keys vary by DSP.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release + custom range:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] },
  "from": "2026-04-01",
  "to": "2026-04-30"
}

// By artist:
{
  "filters": { "artist_names": ["Aurora Nightingale"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams", "all_paidstreams", "all_lyrics", "all_canvas", "all_uniq"],
  "data": [
    {
      "name": "2026-05-11",
      "all_streams": 965,
      "all_paidstreams": 406,
      "all_lyrics": 0,
      "all_canvas": 0,
      "all_uniq": 582
    }
  ]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/graph"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/graph";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/spotify/bar`

Spotify — bar chart payload (proxied).

Exact bar payload shape follows upstream Cabinet JSON for this route.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "bars": [{ "label": "US", "value": 40000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/bar" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/bar" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/bar" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/bar"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/spotify/bar";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/graph/main`

Cross-store summary — main trend graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release + custom range:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] },
  "from": "2026-04-01",
  "to": "2026-04-30"
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams", "all_paidstreams"],
  "data": [{ "name": "2026-05-11", "all_streams": 12000, "all_paidstreams": 4100 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/main" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/main" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/main" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/main"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/main";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/graph/total`

Cross-store summary — totals graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// By artist:
{
  "filters": { "artist_names": ["Aurora Nightingale"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "2026-05-11", "all_streams": 250000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/total"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/total";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/graph/country`

Cross-store summary — breakdown by country.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "US", "all_streams": 80000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/country" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/country" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/country" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/country"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/country";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/graph/os`

Cross-store summary — breakdown by OS.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "iOS", "all_streams": 50000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/os" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/os" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/os" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/os"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/os";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/graph/device_type`

Cross-store summary — breakdown by device type.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "mobile", "all_streams": 90000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/device_type" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/device_type" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/device_type" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/device_type"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/device_type";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/graph/age`

Cross-store summary — age buckets (whole-catalog only, not per-release).

#### Example request (illustrative JSON)

```json
// Whole catalog only (per-release not supported for age/gender):
{
  "filters": {}
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "18-24", "all_streams": 30000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/age" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/age" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/age" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/age"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/age";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/graph/gender`

Cross-store summary — gender breakdown (whole-catalog only, not per-release).

#### Example request (illustrative JSON)

```json
// Whole catalog only (per-release not supported for age/gender):
{
  "filters": {}
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "female", "all_streams": 70000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/gender" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/gender" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/gender" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/gender"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/graph/gender";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/summary/stats`

Cross-store summary — per-platform totals for the caller's catalog or a release/artist subset.

**Narrow by any combination:** `filters.release_public_ids` — use the **`rel_…`** id from **GET /releases/all** (not `mdr_…`). Also: `filters.album_ids` (raw upstream ids), `filters.artist_names` (case-insensitive). Omit all for whole-catalog. Pass `from`/`to` for any custom range — aggregation runs against Gard's daily per-album fact table. Legacy: top-level `gard_release_public_id` / `gard_analytics_album_ids` / `gard_artist_names`. **Unknown id → 400.** **No data yet → 503** with `Retry-After: 30` — Gard schedules a background fill.

#### Example request (illustrative JSON)

```json
{
  "filters": {
    "release_public_ids": ["rel_…"]
  },
  "from": "2026-04-20",
  "to":   "2026-05-15"
}
```

#### Example response (illustrative JSON)

```json
{
  "data": [
    { "name": "yandex",   "streams": 128 },
    { "name": "umavk",    "streams": 436 },
    { "name": "spotify",  "streams": 0   }
  ],
  "lines": ["streams"]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/stats" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/stats" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/stats" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/stats"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/summary/stats";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## GET `/api/v1/music-distributor/analytics/applemusic/filters`

Apple Music analytics filter metadata.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "filters": { "date_range": ["last_7d", "last_28d"] },
  "dimensions": ["album", "track"],
  "metrics": ["plays", "listeners"]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/filters" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/analytics/applemusic/filters",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/analytics/applemusic/filters`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## POST `/api/v1/music-distributor/analytics/applemusic/graph`

Apple Music — graph series.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_plays"],
  "data": [{ "name": "2026-05-11", "all_plays": 1200 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/applemusic/graph/total`

Apple Music — totals graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_plays"],
  "data": [{ "name": "2026-05-11", "all_plays": 60000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph/total"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/graph/total";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/applemusic/bar`

Apple Music — bar chart.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "bars": [{ "label": "Worldwide", "value": 60000 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/bar" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/bar" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/bar" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/bar"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/applemusic/bar";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## GET `/api/v1/music-distributor/analytics/vkclips/filters`

VK Clips analytics filter metadata.

#### Example request (illustrative JSON)

```json
{}
```

#### Example response (illustrative JSON)

```json
{
  "filters": { "date_range": ["last_7d", "last_28d"] },
  "metrics": ["views"]
}
```

#### Example: cURL

```bash
curl -sS "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/filters" \
  -H "X-API-Key: $GARD_API_KEY"
```

#### Example: Python

```python
import os, requests
print(requests.get(
    "https://back.gard-api.org" + "/analytics/vkclips/filters",
    headers={"X-API-Key": os.environ["GARD_API_KEY"]},
).json())
```

#### Example: TypeScript

```typescript
console.log(await (await fetch(
  `https://back.gard-api.org/analytics/vkclips/filters`,
  { headers: { "X-API-Key": process.env.GARD_API_KEY! } },
)).json());
```


## POST `/api/v1/music-distributor/analytics/vkclips/table`

VK Clips analytics table.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["clip", "views"],
  "data": [],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/table"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/vkclips/graph`

VK Clips — graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": []
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/vkclips/graph/total`

VK Clips — totals graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "totals": { "views": 15000 }
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph/total" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph/total"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/vkclips/graph/total";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/yandex/table`

Yandex Music — analytics table.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release + custom range:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] },
  "from": "2026-04-01",
  "to": "2026-04-30"
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["track", "streams", "royalty_streams"],
  "data": [{ "track": "Track A", "streams": 800, "royalty_streams": 600 }],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/table"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/yandex/graph`

Yandex Music — daily graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// By artist:
{
  "filters": { "artist_names": ["Aurora Nightingale"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams", "all_paidstreams"],
  "data": [{ "name": "2026-05-11", "all_streams": 120, "all_paidstreams": 90 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/graph"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/yandex/graph";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/umavk/table`

UMA / VK music — analytics table.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["track", "streams"],
  "data": [],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/table"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/umavk/graph`

UMA / VK music — daily graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "2026-05-11", "all_streams": 50 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/graph"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/umavk/graph";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/mts/table`

MTS Music — analytics table.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["track", "streams"],
  "data": [],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/table"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/mts/graph`

MTS Music — daily graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "2026-05-11", "all_streams": 30 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/graph"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/mts/graph";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/zvooq/table`

Zvooq — analytics table.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "pages": 1,
  "page": 0,
  "columns": ["track", "streams"],
  "data": [],
  "order": {}
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/table" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/table"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/table";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


## POST `/api/v1/music-distributor/analytics/zvooq/graph`

Zvooq — daily graph.

#### Example request (illustrative JSON)

```json
// Whole catalog:
{
  "filters": {}
}

// One release:
{
  "filters": { "release_public_ids": ["rel_ExampleId123"] }
}
```

#### Example response (illustrative JSON)

```json
{
  "lines": ["all_streams"],
  "data": [{ "name": "2026-05-11", "all_streams": 20 }]
}
```

#### Example: cURL

```bash
# Whole catalog (no filters):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{}}'

# One release (use rel_… id from GET /releases/all):
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"release_public_ids":["rel_ExampleId123"]}}'

# By artist + custom date range:
curl -sS -X POST "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/graph" \
  -H "X-API-Key: $GARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"artist_names":["Aurora Nightingale"]},"from":"2026-04-01","to":"2026-04-30"}'
```

#### Example: Python

```python
import os, requests

key = os.environ["GARD_API_KEY"]
url = "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/graph"

# Whole catalog (no filters — Gard uses default 31-day window):
r = requests.post(url, headers={"X-API-Key": key}, json={"filters": {}})
print(r.json())

# One release (use rel_… id from GET /releases/all):
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"release_public_ids": ["rel_ExampleId123"]}
})
print(r.json())

# By artist + custom date range:
r = requests.post(url, headers={"X-API-Key": key}, json={
    "filters": {"artist_names": ["Aurora Nightingale"]},
    "from": "2026-04-01",
    "to": "2026-04-30",
})
print(r.json())
```

#### Example: TypeScript

```typescript
const key = process.env.GARD_API_KEY!;
const url = "https://back.gard-api.org/api/v1/music-distributor/analytics/zvooq/graph";
const headers = { "X-API-Key": key, "Content-Type": "application/json" };

// Whole catalog (no filters — Gard uses default 31-day window):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: {} }),
})).json());

// One release (use rel_… id from GET /releases/all):
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({ filters: { release_public_ids: ["rel_ExampleId123"] } }),
})).json());

// By artist + custom date range:
console.log(await (await fetch(url, {
  method: "POST", headers,
  body: JSON.stringify({
    filters: { artist_names: ["Aurora Nightingale"] },
    from: "2026-04-01",
    to: "2026-04-30",
  }),
})).json());
```


---

## Callback payloads (webhooks)

_Same sample as on the docs page._

```
POST https://your-app.com/webhook
X-Gard-Signature: sha256=...
Content-Type: application/json

{
  "event": "track_ready",
  "track_id": "trk_...",
  "project_id": 128,
  "audio_url": "https://cdn.gard.studio/...mp3",
  "created_at": "2026-04-17T12:34:56Z"
}
```
