🍃 Spring AI Integration

Spring AI Podcast Hosting API: Publish Episodes with Function Calling

PodClaw is the podcast hosting API built for AI agents. Register PodClaw as a callable function in Spring AI and your Java or Kotlin agents can create shows, publish audio files, and distribute episodes to Apple Podcasts and Spotify — all through natural language instructions.

Prerequisites

Add the Spring AI and Spring Boot starters to your Maven or Gradle project:

xml — pom.xml (Maven)
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

Add your PodClaw API key to application.properties:

podclaw.api-key=pc_your_api_key_here podclaw.base-url=https://podclaw.io/api

Define PodClaw Functions

Spring AI function calling works by registering Function<Request, Response> beans. The LLM decides when to call them based on the function description. The beans below expose show creation and episode publishing to your AI agent:

java — PodClawFunctions.java
import org.springframework.ai.model.function.FunctionCallback; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestClient; import java.util.Map; import java.util.function.Function; @Configuration public class PodClawFunctions { @Value("${podclaw.api-key}") private String apiKey; @Value("${podclaw.base-url}") private String baseUrl; public record PublishEpisodeRequest( String showId, String title, String audioUrl, String description ) {} public record PublishEpisodeResponse( String episodeId, String episodeUrl, boolean success ) {} public record CreateShowRequest( String title, String description, String category ) {} public record CreateShowResponse( String showId, String rssUrl ) {} @Bean public Function<PublishEpisodeRequest, PublishEpisodeResponse> publishPodcastEpisode() { return request -> { RestClient client = RestClient.create(); Map<String, Object> body = Map.of( "title", request.title(), "description", request.description() != null ? request.description() : "", "audio_url", request.audioUrl(), "status", "published" ); var response = client.post() .uri(baseUrl + "/shows/" + request.showId() + "/episodes") .header("Authorization", "Bearer " + apiKey) .contentType(org.springframework.http.MediaType.APPLICATION_JSON) .body(body) .retrieve() .toEntity(Map.class) .getBody(); return new PublishEpisodeResponse( (String) response.get("id"), (String) response.get("url"), true ); }; } @Bean public Function<CreateShowRequest, CreateShowResponse> createPodcastShow() { return request -> { RestClient client = RestClient.create(); Map<String, Object> body = Map.of( "title", request.title(), "description", request.description(), "category", request.category() != null ? request.category() : "Technology" ); var response = client.post() .uri(baseUrl + "/shows") .header("Authorization", "Bearer " + apiKey) .contentType(org.springframework.http.MediaType.APPLICATION_JSON) .body(body) .retrieve() .toEntity(Map.class) .getBody(); return new CreateShowResponse( (String) response.get("id"), (String) response.get("rss_url") ); }; } }

Call from a Spring AI ChatClient

Register the function names in your ChatClient request options. The LLM automatically calls the appropriate function when your prompt requires it:

java — PodcastService.java
import org.springframework.ai.chat.client.ChatClient; import org.springframework.stereotype.Service; @Service public class PodcastService { private final ChatClient chatClient; public PodcastService(ChatClient.Builder builder) { this.chatClient = builder.build(); } public String publishWeeklyEpisode(String showId, String audioUrl, String topic) { return chatClient.prompt() .user(String.format( "Publish a podcast episode for show %s. " + "The audio is at %s. " + "Write a compelling title and description about: %s", showId, audioUrl, topic )) .functions("publishPodcastEpisode") .call() .content(); } }
Tip: Pass both createPodcastShow and publishPodcastEpisode as functions in a single call. The LLM will call them in sequence if your prompt asks it to create a new show and immediately publish an episode.

What PodClaw handles automatically

After the episode is published via the API, PodClaw manages distribution:

Frequently Asked Questions

How do I call PodClaw from a Spring AI agent?

Define a @Bean that implements Function<Request, Response> and make HTTP calls to PodClaw's REST API inside it using Spring's RestClient. Register the bean name in your ChatClient options with .functions("beanName") so the LLM can invoke it. Full code is on this page.

Does PodClaw have a Spring Boot starter?

No dedicated starter is needed. PodClaw is a standard REST API. Use Spring's built-in RestClient (Spring 6+) or RestTemplate to call it from any Spring Boot application. The function calling integration requires spring-ai-openai-spring-boot-starter or the equivalent for your LLM provider.

Can Spring AI agents schedule podcast episodes with PodClaw?

Yes. Include a publish_at ISO-8601 timestamp in the episode payload and set status to "scheduled". Your Spring AI agent can determine the publish date from context (content calendar, day-of-week rules, etc.) and PodClaw releases the episode at the specified time.

Ready to ship your first AI podcast?

Get your free PodClaw API key and have your Spring AI agent publishing in minutes.

Get Started Free →