MENU navbar-image

Introduction

Public REST API (v1) for managing podcast feeds, episodes and media files.

This is the reference documentation for v1 of the podcaster public API.

<aside>All endpoints require an OAuth access token or Personal Access Token
issued by Passport. Pass it as a <code>Bearer</code> token in the
<code>Authorization</code> header. Each endpoint lists the scope it requires.</aside>

Authenticating requests

To authenticate requests, include an Authorization header with the value "Bearer {YOUR_ACCESS_TOKEN}".

All authenticated endpoints are marked with a requires authentication badge in the documentation below.

Authentication uses Laravel Passport. You can obtain a token by:

<ul>
    <li>Creating a <b>Personal Access Token</b> in your account settings.</li>
    <li>Performing the OAuth Authorization Code flow against <code>/oauth/authorize</code>.</li>
</ul>

Tokens are scoped — each endpoint declares which scope it requires (e.g. <code>feeds</code>,
<code>media</code>, <code>shows</code>). Read-only variants (<code>*-read-only</code>) are also accepted
where appropriate.

Episodes

Create episode

requires authentication

Adds a new episode. Accessible with scope: shows

Example request:
curl --request POST \
    "https://podcaster.rest/v1/channel/430bed14-957e-4908-b671-70829c67feb3/show" \
    --header "Authorization: Bearer {YOUR_ACCESS_TOKEN}" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "channel_id=123e4567-e89b-12d3-a456-426655440000"\
    --form "status=PUBLISHED"\
    --form "title=Dies ist eine Episode."\
    --form "description="\
    --form "author=Maxima Musterfrau"\
    --form "copyright=Podcast-Team MM"\
    --form "link="\
    --form "file_id=1554927456"\
    --form "itunes[title]="\
    --form "itunes[subtitle]="\
    --form "itunes[summary]="\
    --form "itunes[episode]=0"\
    --form "itunes[episodeType]="\
    --form "itunes[season]=0"\
    --form "itunes[logo]="\
    --form "itunes[explicit]="\
    --form "itunes[block]=1"\
    --form "itunes[author]="\
    --form "publishing_date=2021-08-26"\
    --form "publishing_time=12:10:59"\
    --form "podcastindex[episode_node_value]=4326.41688"\
    --form "podcastindex[episode_display]=m"\
    --form "podcastindex[chapter_url]=https://www.gulgowski.com/nihil-accusantium-harum-mollitia-modi-deserunt"\
    --form "podcastindex[chapter_type]=w"\
    --form "podcastindex[image_srcset]=architecto"\
    --form "podcastindex[license_node_value]=n"\
    --form "podcastindex[license_url]=http://crooks.biz/et-fugiat-sunt-nihil-accusantium"\
    --form "podcastindex[location_node_value]=n"\
    --form "podcastindex[location_geo_latitude]=4326.41688"\
    --form "podcastindex[location_geo_longitude]=4326.41688"\
    --form "podcastindex[location_osm]=m"\
    --form "podcastindex[season_node_value]=16"\
    --form "podcastindex[season_name]=n"\
    --form "write_metadata="\
    --form "media=@/private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpllies0dppaer7AfnLSN" 
const url = new URL(
    "https://podcaster.rest/v1/channel/430bed14-957e-4908-b671-70829c67feb3/show"
);

const headers = {
    "Authorization": "Bearer {YOUR_ACCESS_TOKEN}",
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('channel_id', '123e4567-e89b-12d3-a456-426655440000');
body.append('status', 'PUBLISHED');
body.append('title', 'Dies ist eine Episode.');
body.append('description', '');
body.append('author', 'Maxima Musterfrau');
body.append('copyright', 'Podcast-Team MM');
body.append('link', '');
body.append('file_id', '1554927456');
body.append('itunes[title]', '');
body.append('itunes[subtitle]', '');
body.append('itunes[summary]', '');
body.append('itunes[episode]', '0');
body.append('itunes[episodeType]', '');
body.append('itunes[season]', '0');
body.append('itunes[logo]', '');
body.append('itunes[explicit]', '');
body.append('itunes[block]', '1');
body.append('itunes[author]', '');
body.append('publishing_date', '2021-08-26');
body.append('publishing_time', '12:10:59');
body.append('podcastindex[episode_node_value]', '4326.41688');
body.append('podcastindex[episode_display]', 'm');
body.append('podcastindex[chapter_url]', 'https://www.gulgowski.com/nihil-accusantium-harum-mollitia-modi-deserunt');
body.append('podcastindex[chapter_type]', 'w');
body.append('podcastindex[image_srcset]', 'architecto');
body.append('podcastindex[license_node_value]', 'n');
body.append('podcastindex[license_url]', 'http://crooks.biz/et-fugiat-sunt-nihil-accusantium');
body.append('podcastindex[location_node_value]', 'n');
body.append('podcastindex[location_geo_latitude]', '4326.41688');
body.append('podcastindex[location_geo_longitude]', '4326.41688');
body.append('podcastindex[location_osm]', 'm');
body.append('podcastindex[season_node_value]', '16');
body.append('podcastindex[season_name]', 'n');
body.append('write_metadata', '');
body.append('media', document.querySelector('input[name="media"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://podcaster.rest/v1/channel/430bed14-957e-4908-b671-70829c67feb3/show';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_ACCESS_TOKEN}',
            'Content-Type' => 'multipart/form-data',
            'Accept' => 'application/json',
        ],
        'multipart' => [
            [
                'name' => 'channel_id',
                'contents' => '123e4567-e89b-12d3-a456-426655440000'
            ],
            [
                'name' => 'status',
                'contents' => 'PUBLISHED'
            ],
            [
                'name' => 'title',
                'contents' => 'Dies ist eine Episode.'
            ],
            [
                'name' => 'description',
                'contents' => ''
            ],
            [
                'name' => 'author',
                'contents' => 'Maxima Musterfrau'
            ],
            [
                'name' => 'copyright',
                'contents' => 'Podcast-Team MM'
            ],
            [
                'name' => 'link',
                'contents' => ''
            ],
            [
                'name' => 'file_id',
                'contents' => '1554927456'
            ],
            [
                'name' => 'itunes[title]',
                'contents' => ''
            ],
            [
                'name' => 'itunes[subtitle]',
                'contents' => ''
            ],
            [
                'name' => 'itunes[summary]',
                'contents' => ''
            ],
            [
                'name' => 'itunes[episode]',
                'contents' => '0'
            ],
            [
                'name' => 'itunes[episodeType]',
                'contents' => ''
            ],
            [
                'name' => 'itunes[season]',
                'contents' => '0'
            ],
            [
                'name' => 'itunes[logo]',
                'contents' => ''
            ],
            [
                'name' => 'itunes[explicit]',
                'contents' => ''
            ],
            [
                'name' => 'itunes[block]',
                'contents' => '1'
            ],
            [
                'name' => 'itunes[author]',
                'contents' => ''
            ],
            [
                'name' => 'publishing_date',
                'contents' => '2021-08-26'
            ],
            [
                'name' => 'publishing_time',
                'contents' => '12:10:59'
            ],
            [
                'name' => 'podcastindex[episode_node_value]',
                'contents' => '4326.41688'
            ],
            [
                'name' => 'podcastindex[episode_display]',
                'contents' => 'm'
            ],
            [
                'name' => 'podcastindex[chapter_url]',
                'contents' => 'https://www.gulgowski.com/nihil-accusantium-harum-mollitia-modi-deserunt'
            ],
            [
                'name' => 'podcastindex[chapter_type]',
                'contents' => 'w'
            ],
            [
                'name' => 'podcastindex[image_srcset]',
                'contents' => 'architecto'
            ],
            [
                'name' => 'podcastindex[license_node_value]',
                'contents' => 'n'
            ],
            [
                'name' => 'podcastindex[license_url]',
                'contents' => 'http://crooks.biz/et-fugiat-sunt-nihil-accusantium'
            ],
            [
                'name' => 'podcastindex[location_node_value]',
                'contents' => 'n'
            ],
            [
                'name' => 'podcastindex[location_geo_latitude]',
                'contents' => '4326.41688'
            ],
            [
                'name' => 'podcastindex[location_geo_longitude]',
                'contents' => '4326.41688'
            ],
            [
                'name' => 'podcastindex[location_osm]',
                'contents' => 'm'
            ],
            [
                'name' => 'podcastindex[season_node_value]',
                'contents' => '16'
            ],
            [
                'name' => 'podcastindex[season_name]',
                'contents' => 'n'
            ],
            [
                'name' => 'write_metadata',
                'contents' => ''
            ],
            [
                'name' => 'media',
                'contents' => fopen('/private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpllies0dppaer7AfnLSN', 'r')
            ],
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://podcaster.rest/v1/channel/430bed14-957e-4908-b671-70829c67feb3/show'
files = {
  'channel_id': (None, '123e4567-e89b-12d3-a456-426655440000'),
  'status': (None, 'PUBLISHED'),
  'title': (None, 'Dies ist eine Episode.'),
  'description': (None, ''),
  'author': (None, 'Maxima Musterfrau'),
  'copyright': (None, 'Podcast-Team MM'),
  'link': (None, ''),
  'file_id': (None, '1554927456'),
  'itunes[title]': (None, ''),
  'itunes[subtitle]': (None, ''),
  'itunes[summary]': (None, ''),
  'itunes[episode]': (None, '0'),
  'itunes[episodeType]': (None, ''),
  'itunes[season]': (None, '0'),
  'itunes[logo]': (None, ''),
  'itunes[explicit]': (None, ''),
  'itunes[block]': (None, '1'),
  'itunes[author]': (None, ''),
  'publishing_date': (None, '2021-08-26'),
  'publishing_time': (None, '12:10:59'),
  'podcastindex[episode_node_value]': (None, '4326.41688'),
  'podcastindex[episode_display]': (None, 'm'),
  'podcastindex[chapter_url]': (None, 'https://www.gulgowski.com/nihil-accusantium-harum-mollitia-modi-deserunt'),
  'podcastindex[chapter_type]': (None, 'w'),
  'podcastindex[image_srcset]': (None, 'architecto'),
  'podcastindex[license_node_value]': (None, 'n'),
  'podcastindex[license_url]': (None, 'http://crooks.biz/et-fugiat-sunt-nihil-accusantium'),
  'podcastindex[location_node_value]': (None, 'n'),
  'podcastindex[location_geo_latitude]': (None, '4326.41688'),
  'podcastindex[location_geo_longitude]': (None, '4326.41688'),
  'podcastindex[location_osm]': (None, 'm'),
  'podcastindex[season_node_value]': (None, '16'),
  'podcastindex[season_name]': (None, 'n'),
  'write_metadata': (None, ''),
  'media': open('/private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpllies0dppaer7AfnLSN', 'rb')}
payload = {
    "channel_id": "123e4567-e89b-12d3-a456-426655440000",
    "status": "PUBLISHED",
    "title": "Dies ist eine Episode.",
    "description": "",
    "author": "Maxima Musterfrau",
    "copyright": "Podcast-Team MM",
    "link": "",
    "file_id": "1554927456",
    "itunes": {
        "title": "",
        "subtitle": "",
        "summary": "",
        "episode": 0,
        "episodeType": "",
        "season": 0,
        "logo": "",
        "explicit": false,
        "block": true,
        "author": ""
    },
    "publishing_date": "2021-08-26",
    "publishing_time": "12:10:59",
    "podcastindex": {
        "episode_node_value": 4326.41688,
        "episode_display": "m",
        "chapter_url": "https:\/\/www.gulgowski.com\/nihil-accusantium-harum-mollitia-modi-deserunt",
        "chapter_type": "w",
        "image_srcset": "architecto",
        "license_node_value": "n",
        "license_url": "http:\/\/crooks.biz\/et-fugiat-sunt-nihil-accusantium",
        "location_node_value": "n",
        "location_geo_latitude": 4326.41688,
        "location_geo_longitude": 4326.41688,
        "location_osm": "m",
        "season_node_value": 16,
        "season_name": "n"
    },
    "write_metadata": false
}
headers = {
  'Authorization': 'Bearer {YOUR_ACCESS_TOKEN}',
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, files=files)
response.json()

Request      

POST v1/channel/{channel_uuid}/show

Headers

Authorization        

Example: Bearer {YOUR_ACCESS_TOKEN}

Content-Type        

Example: multipart/form-data

Accept        

Example: application/json

URL Parameters

channel_uuid   string     

Example: 430bed14-957e-4908-b671-70829c67feb3

Body Parameters

channel_id   string  optional    

UUId des Podcasts. Example: 123e4567-e89b-12d3-a456-426655440000

status   string  optional    

Status der Episode: DRAFT (Entwurf), PUBLISHED (Veröffentlicht) Example: PUBLISHED

title   string     

Titel der Episode. :Attribute darf maximal 255 Zeichen haben. Example: Dies ist eine Episode.

description   string     

Beschreibung der Episode. :Attribute darf maximal 4000 Zeichen haben.

author   string     

Autor der Episode. :Attribute darf maximal 255 Zeichen haben. Example: Maxima Musterfrau

copyright   string  optional    

Angabe zu Nutzerrechten. :Attribute darf maximal 255 Zeichen haben. Example: Podcast-Team MM

link   string  optional    

Must be a valid URL.

file_id   string  optional    

ID einer Medien-Datei. Example: 1554927456

itunes   object  optional    
title   string  optional    

Apple Podcast-spezifischer Titel der Episode. :Attribute darf maximal 255 Zeichen haben.

subtitle   string  optional    

Apple Podcast-spezifischer Untertitel der Episode. :Attribute darf maximal 255 Zeichen haben.

summary   string  optional    

Apple Podcast-spezifische Zusammenfassung der Episode (ohne HTML). :Attribute darf maximal 4000 Zeichen haben.

episode   integer  optional    

Example: 0

episodeType   string     
Must be one of:
  • full
  • trailer
  • bonus
season   integer  optional    

Example: 0

logo   string  optional    
explicit   boolean     

Example: false

block   boolean  optional    

Example: true

author   string  optional    

:Attribute darf maximal 255 Zeichen haben.

publishing_date   string     

Must be a valid date in the format Y-m-d. Example: 2021-08-26

publishing_time   string     

Must be a valid date in the format H:i:s. Example: 12:10:59

media   file  optional    

Must be a file. Example: /private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpllies0dppaer7AfnLSN

podcastindex   object  optional    
episode_node_value   number  optional    

Example: 4326.41688

episode_display   string  optional    

:Attribute darf maximal 255 Zeichen haben. Example: m

chapter_url   string  optional    

:Attribute darf maximal 255 Zeichen haben. Example: https://www.gulgowski.com/nihil-accusantium-harum-mollitia-modi-deserunt

chapter_type   string  optional    

:Attribute darf maximal 50 Zeichen haben. Example: w

image_srcset   string  optional    

Example: architecto

license_node_value   string  optional    

:Attribute darf maximal 255 Zeichen haben. Example: n

license_url   string  optional    

:Attribute darf maximal 255 Zeichen haben. Example: http://crooks.biz/et-fugiat-sunt-nihil-accusantium

location_node_value   string  optional    

:Attribute darf maximal 255 Zeichen haben. Example: n

location_geo_latitude   number  optional    

Example: 4326.41688

location_geo_longitude   number  optional    

Example: 4326.41688

location_osm   string  optional    

:Attribute darf maximal 255 Zeichen haben. Example: m

season_node_value   integer  optional    

Example: 16

season_name   string  optional    

:Attribute darf maximal 255 Zeichen haben. Example: n

transcript   string  optional    
write_metadata   boolean  optional    

Example: false

Media

Upload file

requires authentication

Stores a file in the media manager.

Example request:
curl --request POST \
    "https://podcaster.rest/v1/media" \
    --header "Authorization: Bearer {YOUR_ACCESS_TOKEN}" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "media=@/private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpvdunamvchduu3DYMcTI" 
const url = new URL(
    "https://podcaster.rest/v1/media"
);

const headers = {
    "Authorization": "Bearer {YOUR_ACCESS_TOKEN}",
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('media', document.querySelector('input[name="media"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://podcaster.rest/v1/media';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_ACCESS_TOKEN}',
            'Content-Type' => 'multipart/form-data',
            'Accept' => 'application/json',
        ],
        'multipart' => [
            [
                'name' => 'media',
                'contents' => fopen('/private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpvdunamvchduu3DYMcTI', 'r')
            ],
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://podcaster.rest/v1/media'
files = {
  'media': open('/private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpvdunamvchduu3DYMcTI', 'rb')}
headers = {
  'Authorization': 'Bearer {YOUR_ACCESS_TOKEN}',
  'Content-Type': 'multipart/form-data',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, files=files)
response.json()

Request      

POST v1/media

Headers

Authorization        

Example: Bearer {YOUR_ACCESS_TOKEN}

Content-Type        

Example: multipart/form-data

Accept        

Example: application/json

Body Parameters

media   file     

The media file to upload. Example: /private/var/folders/kp/gjrd14bx1pz07y3xg3bylmgr0000gp/T/phpvdunamvchduu3DYMcTI

Podcasts

List podcasts

requires authentication

Returns a list of podcasts. Accessible with scopes: feeds,feeds-read-only

Example request:
curl --request GET \
    --get "https://podcaster.rest/v1/channels?page%5Bnumber%5D=1&page%5Bsize%5D=10" \
    --header "Authorization: Bearer {YOUR_ACCESS_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://podcaster.rest/v1/channels"
);

const params = {
    "page[number]": "1",
    "page[size]": "10",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_ACCESS_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://podcaster.rest/v1/channels';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_ACCESS_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'page[number]' => '1',
            'page[size]' => '10',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://podcaster.rest/v1/channels'
params = {
  'page[number]': '1',
  'page[size]': '10',
}
headers = {
  'Authorization': 'Bearer {YOUR_ACCESS_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "type": "channel",
            "id": "6c3f12f2-dce3-4084-b332-eaa0de6d914b",
            "links": {
                "self": "https://podcaster.rest/api/channels/6c3f12f2-dce3-4084-b332-eaa0de6d914b",
                "rss": "http://testing-gabrieljeanette2464.podcaster.de.test/fAxE239433TsACgaSLfF.rss",
                "web": "",
                "logo": "http://podcaster.rest/images/help/cover_missing.svg?v=1"
            },
            "attributes": {
                "rss": {
                    "title": "nulla",
                    "subtitle": "Deserunt dolorem ab.",
                    "description": "Dolorum ut ullam sunt praesentium. Laudantium sequi quo animi optio architecto. Qui ut quas sequi ullam voluptas sunt consequatur.",
                    "copyright": "Aliquam."
                },
                "logo": null,
                "is_explicit": true,
                "is_protected": null,
                "imported": null,
                "podcastindex": {
                    "guid": "0rU3MmkNikCCDCX7b5l2",
                    "medium": "est",
                    "podping": false,
                    "license": {
                        "identifier": "Inventore sed sequi.",
                        "url": "http://jordan.de/quisquam-omnis-eveniet-recusandae-recusandae-assumenda-amet-ratione"
                    },
                    "locked": {
                        "value": "no",
                        "owner": "irene.gunther@t-online.de"
                    },
                    "update_frequency": {
                        "description": "Täglich",
                        "complete": false,
                        "dtstart": "2026-06-01T07:24:36.000000Z",
                        "rrule": "FREQ=DAILY"
                    },
                    "chat": [],
                    "trailer": [],
                    "blocks": [],
                    "fundings": [],
                    "images": [],
                    "locations": [],
                    "persons": [],
                    "txts": [],
                    "social_interacts": [],
                    "remote_items": [],
                    "podrolls": [],
                    "publisher": [],
                    "live_items": [],
                    "values": []
                }
            },
            "shows_count": 0
        },
        {
            "type": "channel",
            "id": "aa4598f5-e461-4200-bc3f-8ffa0de3b680",
            "links": {
                "self": "https://podcaster.rest/api/channels/aa4598f5-e461-4200-bc3f-8ffa0de3b680",
                "rss": "http://testing-gabrieljeanette2464.podcaster.de.test/QSxDWAdrW9jMKhEzioey.rss",
                "web": "",
                "logo": "http://podcaster.rest/images/help/cover_missing.svg?v=1"
            },
            "attributes": {
                "rss": {
                    "title": "laboriosam",
                    "subtitle": "Labore quia.",
                    "description": "Nihil est debitis quia omnis ab dolorum aperiam. Amet voluptas aspernatur repellat rerum quas quia. Officia placeat soluta qui optio reiciendis. Esse voluptatibus assumenda voluptatibus numquam.",
                    "copyright": "Aliquam."
                },
                "logo": null,
                "is_explicit": true,
                "is_protected": null,
                "imported": null,
                "podcastindex": {
                    "guid": "AQq5grGGyLjsPvrjRRJW",
                    "medium": "pariatur",
                    "podping": false,
                    "license": {
                        "identifier": "Ut ut nulla fugit.",
                        "url": "http://www.schneider.net/et-corporis-rerum-consequatur-accusamus"
                    },
                    "locked": {
                        "value": "no",
                        "owner": "mroth@lang.net"
                    },
                    "update_frequency": {
                        "description": "Täglich",
                        "complete": true,
                        "dtstart": "2026-06-01T07:24:36.000000Z",
                        "rrule": "FREQ=DAILY"
                    },
                    "chat": [],
                    "trailer": [],
                    "blocks": [],
                    "fundings": [],
                    "images": [],
                    "locations": [],
                    "persons": [],
                    "txts": [],
                    "social_interacts": [],
                    "remote_items": [],
                    "podrolls": [],
                    "publisher": [],
                    "live_items": [],
                    "values": []
                }
            },
            "shows_count": 0
        }
    ]
}
 

Request      

GET v1/channels

Headers

Authorization        

Example: Bearer {YOUR_ACCESS_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

page[number]   integer  optional    

Used for pagination. The page number. Example: 1

page[size]   integer  optional    

Used for pagination. The page size. Example: 10