Come generare podcast con l'API di Podhoc: guida completa
Genera podcast con IA in modo programmatico tramite l'API REST di Podhoc. Autenticazione, ciclo crea-interroga-scarica, limiti di frequenza, stima dei crediti ed esempi Python e Node.js pronti per la produzione.
Genera podcast con IA in modo programmatico tramite l’API di Podhoc
Per generare un podcast con l’API di Podhoc, invia una richiesta POST a https://api-ext.podhoc.com/v1/podcasts con il tuo header X-Api-Key, gli URL sorgente, una durata target tra 1 e 120 minuti e una configurazione opzionale di stile e voci. L’endpoint restituisce un podcast_id che interroghi su /v1/podcasts/{id}/status fino al completamento (di solito 2-5 minuti), poi chiami /v1/podcasts/{id}/download per ottenere un URL MP3 prefirmato valido per un’ora.
L’API è progettata per un singolo ciclo crea-interroga-scarica. Non ci sono stream, callback o webhook (per ora). L’autenticazione è un singolo header statico. Se hai mai chiamato un’API REST, puoi integrare Podhoc in meno di un’ora.
Nota di traduzione: da rivedere da un madrelingua italiano.
A cosa serve l’API
L’API di Podhoc espone la stessa pipeline di generazione che alimenta la web app, ridotta a un piccolo set di primitive:
- Creazione programmatica di podcast da URL pubblici.
- Stima del costo prima di spendere crediti.
- Introspezione dell’account — saldo crediti, cronologia uso, livello attuale.
- Gestione del ciclo di vita — interrogazione di stato e download prefirmato.
La pipeline dietro queste primitive è lo stesso sistema in cinque fasi descritto in Cos’è un podcast IA?: ingestione, comprensione, riformattazione audio, scelta del formato e sintesi vocale. L’API la rende semplicemente scriptabile.
Casi d’uso comuni:
- Un prodotto SaaS che trasforma URL caricati dai clienti in audio di onboarding.
- Uno strumento interno che converte newsletter settimanali in episodi pronti per il tragitto.
- Una piattaforma di apprendimento che genera automaticamente versioni audio dei nuovi moduli del corso.
- Un flusso di ricerca che sintetizza una serie di paper in un singolo briefing di 30 minuti.
Per altro, vedi Idee di integrazione con l’API.
Passo 1 — Provisiona un token
L’accesso API è limitato al piano Pro (29 €/mese, 3500 crediti) e superiori. Una volta aggiornato l’abbonamento, vai su app.podhoc.com/account/api-access e crea un token.
Ci sono due varianti:
- Token di test — prefisso
phk_test_…, più economici (moltiplicatore 1,5x), set di funzionalità ristretto. Usali durante sviluppo e test di integrazione in CI. - Token di produzione — prefisso
phk_prod_…, set completo di funzionalità, moltiplicatore 2,5x.
Tratta i token come password. Conservali in un gestore di segreti (AWS Secrets Manager, HashiCorp Vault, Doppler) e non commetterli mai nel controllo del codice. L’API rifiuta le richieste con token trapelati o revocati con un 401 UNAUTHORIZED.
L’autenticazione è un singolo header su ogni richiesta:
X-Api-Key: phk_prod_a1b2c3d4e5f6...
L’URL base è https://api-ext.podhoc.com/v1. Tutti gli endpoint restituiscono JSON con un booleano success, un oggetto data in caso di successo, un oggetto error in caso di errore e un oggetto meta con request_id più campi relativi ai crediti. La busta è ispirata alle stesse convenzioni che Anthropic e altri provider IA moderni seguono: struttura prevedibile, gestione degli errori prevedibile.
Passo 2 — Stima prima il costo
Prima di chiamare l’endpoint di creazione, chiedi all’API quanto addebiterà. L’endpoint di stima è gratuito e ti permette di implementare controlli di spesa in modo pulito.
curl "https://api-ext.podhoc.com/v1/estimate-cost?duration_minutes=30&source_count=2&voice_count=2" \
-H "X-Api-Key: $PODHOC_API_KEY"
La risposta dettaglia il costo così puoi applicare la tua logica di policy:
{
"success": true,
"data": {
"base_credits": 114,
"credit_multiplier": 1.5,
"final_credits": 171,
"breakdown": {
"base_cost": 75,
"multi_source_bonus": 20,
"custom_weights_bonus": 0,
"voice_multiplier": 1.2,
"subtotal_before_cap": 114,
"cap_applied": null,
"tier_max_cost": 500
},
"formula": "max(30, ceil(30 x 2.5)) + 20 x 1.2 = 114 x multiplier = 171"
}
}
La formula di pricing ha un tetto di 500 crediti per richiesta, applicato dopo i moltiplicatori di voce, i bonus multi-source e i bonus pesi personalizzati. Usa il dettaglio per mostrare ai tuoi utenti finali un’anteprima “questo episodio costerà N crediti” prima che confermino.
Puoi anche recuperare il tuo saldo in tempo reale:
curl https://api-ext.podhoc.com/v1/account/credits \
-H "X-Api-Key: $PODHOC_API_KEY"
Passo 3 — Crea il podcast
L’endpoint di creazione è quello che fa lavoro e addebita crediti. Il payload minimo è una lista di URL:
curl -X POST https://api-ext.podhoc.com/v1/podcasts \
-H "X-Api-Key: $PODHOC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"urls": ["https://example.com/article"],
"language": "it",
"target_duration_minutes": 15,
"style": "deep_dive",
"voice_config": { "voices": 2 }
}'
La risposta (HTTP 202 Accepted) ti dà l’identificatore che interrogherai:
{
"success": true,
"data": {
"podcast_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "processing",
"estimated_duration_minutes": 15,
"credits_charged": 113
},
"meta": {
"request_id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"credits_charged": 113,
"credit_balance": 3387
}
}
Il parametro style è uno degli otto formati pedagogici supportati da Podhoc — deep_dive, didactic, feynman_technique, critique, debate, simplified_explanation, pedagogical_framework, alchemist_formula. Ognuno produce un output marcatamente diverso per la stessa sorgente. Vedi la guida agli stili audio per sapere quando scegliere quale.
Il parametro language accetta uno qualsiasi dei 74 codici di lingua supportati — en-US, es, fr, de, it, ca, ar, ru, più altri 66. Lingua sorgente e di output sono disaccoppiate: passa un URL inglese con language: "it" e ottieni un podcast in italiano.
Passo 4 — Interroga l’endpoint di stato
La generazione è asincrona. Il podcast_id è il tuo handle per il resto del ciclo di vita.
curl https://api-ext.podhoc.com/v1/podcasts/$PODCAST_ID/status \
-H "X-Api-Key: $PODHOC_API_KEY"
Lo stato attraversa quattro valori:
requested— accettato, in coda.processing— in esecuzione attiva.completed— fatto, pronto per il download.failed— errore terminale; consulta i dettagli della risposta.
Interroga ogni 10 secondi con un piccolo backoff. La maggior parte dei podcast si completa in 2-5 minuti indipendentemente dalla lunghezza della sorgente, perché la pipeline parallelizza su GPU cloud. Un client ragionevole implementa l’interrogazione con un tetto rigido (15 minuti) e mostra una UI “in corso” all’utente finale.
Passo 5 — Scarica l’MP3
L’endpoint di download restituisce un URL S3 prefirmato che scade dopo un’ora:
curl https://api-ext.podhoc.com/v1/podcasts/$PODCAST_ID/download \
-H "X-Api-Key: $PODHOC_API_KEY"
{
"success": true,
"data": {
"download_url": "https://s3.amazonaws.com/...",
"expires_at": "2026-05-06T11:00:00+00:00",
"format": "mp3",
"duration_seconds": 900
}
}
Trasmetti l’URL al tuo storage. Se ti serve un riferimento permanente, copia i byte nel tuo bucket S3 / GCS / Azure — l’URL prefirmato è di breve durata, ma l’audio che recuperi vive per sempre nel tuo ambiente.
Un’integrazione completa in Python
Ecco lo stesso ciclo come script eseguibile. Stima il costo, controlla il saldo, crea, interroga e scarica. La gestione degli errori è volutamente esplicita per farti vedere dove ogni contratto API viene applicato.
import os
import time
import requests
API_KEY = os.environ["PODHOC_API_KEY"]
BASE = "https://api-ext.podhoc.com/v1"
HEADERS = {"X-Api-Key": API_KEY, "Content-Type": "application/json"}
def estimate(duration: int, sources: int, voices: int) -> int:
r = requests.get(
f"{BASE}/estimate-cost",
headers={"X-Api-Key": API_KEY},
params={
"duration_minutes": duration,
"source_count": sources,
"voice_count": voices,
},
timeout=15,
)
r.raise_for_status()
return r.json()["data"]["final_credits"]
def balance() -> int:
r = requests.get(f"{BASE}/account/credits", headers={"X-Api-Key": API_KEY}, timeout=15)
r.raise_for_status()
return r.json()["data"]["credits"]
def create(urls: list[str], duration: int, language: str, style: str) -> str:
r = requests.post(
f"{BASE}/podcasts",
headers=HEADERS,
json={
"urls": urls,
"language": language,
"target_duration_minutes": duration,
"style": style,
},
timeout=30,
)
r.raise_for_status()
return r.json()["data"]["podcast_id"]
def wait_for(podcast_id: str, max_seconds: int = 900) -> None:
started = time.time()
while time.time() - started < max_seconds:
r = requests.get(
f"{BASE}/podcasts/{podcast_id}/status",
headers={"X-Api-Key": API_KEY},
timeout=15,
)
r.raise_for_status()
status = r.json()["data"]["status"]
if status == "completed":
return
if status == "failed":
raise RuntimeError(f"Generation failed: {r.json()}")
time.sleep(10)
raise TimeoutError(f"Podcast {podcast_id} did not complete within {max_seconds}s")
def download(podcast_id: str, dest: str) -> None:
r = requests.get(
f"{BASE}/podcasts/{podcast_id}/download",
headers={"X-Api-Key": API_KEY},
timeout=15,
)
r.raise_for_status()
audio = requests.get(r.json()["data"]["download_url"], timeout=60)
audio.raise_for_status()
with open(dest, "wb") as f:
f.write(audio.content)
if __name__ == "__main__":
cost = estimate(duration=15, sources=1, voices=2)
if balance() < cost:
raise SystemExit(f"Insufficient credits ({balance()} < {cost})")
pid = create(
urls=["https://example.com/article"],
duration=15,
language="it",
style="deep_dive",
)
wait_for(pid)
download(pid, "podcast.mp3")
print(f"Saved podcast.mp3")
Un equivalente Node.js usa lo stesso flusso con fetch. Entrambi sono documentati nella referenza API completa.
Limiti di frequenza e come rispettarli
| Tipo di token | Richieste/minuto | Richieste/ora | Generazioni concorrenti |
|---|---|---|---|
| Test | 2 | 20 | 1 |
| Produzione | 30 | 300 | 5 |
Raggiungere un limite restituisce HTTP 429 con header Retry-After. Un client corretto rispetta quell’header e accoda il prossimo tentativo di conseguenza. I limiti di produzione sono calibrati per integrazioni SaaS tipiche — la maggior parte dei team non vi si avvicina mai. Se lo fai, parlaci di una quota enterprise.
La pratica standard per irrobustire qualsiasi client API si applica qui: imposta un timeout su ogni richiesta (15-30 secondi bastano), limita i retry (tre tentativi con backoff esponenziale) e mostra gli errori 5xx al tuo operatore invece di ingoiarli. La RFC OAuth 2.1 è eccessiva per un’API a token statico come questa, ma la sua igiene operativa vale la pena di essere presa in prestito — registra gli ID di richiesta (meta.request_id) su ogni errore così il supporto può correlare.
Cosa i token di test non possono fare
I token di test sono volutamente ristretti perché tu possa integrare a basso costo senza bruciare crediti di produzione. In particolare:
- Durata massima dell’episodio: 5 minuti.
- Lingue consentite: solo inglese (
en-US,en). - URL per richiesta: 1.
- Voci massime: 2.
custom_focus,source_weightseauto_publish: non disponibili.
Qualsiasi tentativo restituisce 400 TEST_TOKEN_RESTRICTED. Passa a un token di produzione (sempre nello stesso account Pro) quando sei pronto a spedire.
Webhook, caricamenti di file e ciò che non è ancora supportato
Alcune funzionalità che esistono nella web app non sono nell’API oggi:
- Caricamenti di file. Puoi passare URL ma non byte grezzi PDF / DOCX / TXT. Se il tuo contenuto è dietro autenticazione, ospitalo pubblicamente con un URL firmato o contattaci per una rotta enterprise.
- Corpi di testo grezzi. Il parametro
urlsè l’unico meccanismo di ingestione; non puoi POSTare un campotext_content. - Webhook / callback. I cambi di stato si osservano tramite interrogazione. Un livello di webhook è nella nostra roadmap; per ora, un loop di interrogazione ogni 10 secondi è il pattern raccomandato.
Queste lacune sono intenzionali — l’API esce con una superficie minima funzionale e la espanderemo man mano che i pattern di integrazione si stabilizzano.
Cosa costruire dopo
Una volta che la prima integrazione gira, il prossimo passo naturale è adottare l’API in una vera superficie di prodotto. Alcuni punti di partenza:
- Abbina l’API a un bot Telegram per permettere ai tuoi utenti di scatenare la generazione dalla chat.
- Combina la creazione di podcast con i nostri otto stili audio per consentire ai tuoi utenti di scegliere il trattamento pedagogico per sorgente.
- Pilota flussi PDF a podcast ospitando prima il PDF pubblicamente, poi passando l’URL.
- Leggi Idee di integrazione con l’API per pattern concreti che abbiamo visto i team spedire con l’API nei primi 30 giorni.
L’obiettivo dell’API è portare Podhoc fuori dal browser e dentro il tuo prodotto. Il ciclo in cinque passi è piccolo di proposito. Costruisci il wrapper sottile, prova contro i tuoi URL e itera.
Domande frequenti
- A cosa serve l'API di Podhoc?
- L’API di Podhoc consente di generare podcast con IA in modo programmatico a partire da URL pubblici. Puoi integrare la creazione di podcast nel tuo prodotto, automatizzare la generazione in batch di episodi, costruire strumenti interni che trasformano documenti in audio e orchestrare flussi multi-step che combinano la generazione con altri servizi.
- Quale piano include l'accesso API?
- L’accesso API è incluso nel piano Pro (29 €/mese, 3500 crediti) e superiori. I piani Free e Creator non includono token API. Trovi i prezzi su podhoc.com e puoi creare token su app.podhoc.com/account/api-access una volta sottoscritto.
- Qual è la differenza tra token di test e di produzione?
- I token di test (
phk_test_…) costano meno (moltiplicatore di crediti 1,5x) ma hanno restrizioni: episodi di 5 minuti al massimo, solo inglese, 1 URL per richiesta, massimo 2 voci, niente focus personalizzato, niente pesatura sorgenti, niente pubblicazione automatica. Sono pensati per sviluppo e test di integrazione. I token di produzione (phk_prod_…) costano 2,5x crediti e sbloccano l’insieme completo: episodi di 120 minuti, tutte le 73 lingue di output, URL illimitati per richiesta, tutte le opzioni di voce, focus personalizzato, pesatura sorgenti e pubblicazione automatica. - Quali sono i limiti di frequenza dell'API?
- Token di test: 2 richieste/minuto, 20 richieste/ora, 1 generazione concorrente. Token di produzione: 30 richieste/minuto, 300 richieste/ora, 5 generazioni concorrenti. Quando raggiungi un limite, l’API restituisce HTTP 429 con header Retry-After che indica quando ritentare. I limiti di produzione sono calibrati per integrazioni SaaS tipiche; se ti serve più throughput, contattaci per una quota enterprise.
- Quanto dura la generazione e come dovrei interrogare?
- La maggior parte dei podcast si completa in 2-5 minuti indipendentemente dalla lunghezza della sorgente, perché LLM e pipeline TTS girano in parallelo su GPU cloud. Interroga GET /v1/podcasts/{id}/status ogni 10 secondi con backoff esponenziale se vuoi essere educato. Fermati su stato
completedofailed. Per integrazioni sensibili alla latenza, mostra una UI generica “Generazione in corso” mentre interroghi in background. - Quali sorgenti posso passare all'API?
- L’API accetta solo URL pubblici — articoli, post di blog, paper di ricerca su arXiv o repository istituzionali, video YouTube con trascrizione e qualsiasi altro URL il cui contenuto sia raggiungibile senza autenticazione. Caricamenti di file (PDF/DOCX/TXT) e contenuto testuale grezzo non sono supportati via API oggi; se le tue sorgenti sono dietro autenticazione, ospitale prima pubblicamente o contattaci per discutere un’integrazione enterprise.
- Come si calcola il costo in crediti?
- Il costo base è
max(30, ceil(duration_minutes × 2,5)). Il bonus multi-source aggiunge 20 crediti, quello pesi personalizzati 10, multi-voice moltiplica il subtotale per 1,2, e il tetto è 500 crediti per richiesta. Il costo finale API moltiplica la base per 1,5 (token di test) o 2,5 (token di produzione). Usa GET /v1/estimate-cost per visualizzare in anteprima — restituisce il dettaglio completo. - Quali codici di errore devo gestire?
- I più comuni sono 400 INVALID_REQUEST (campi mancanti o malformati), 400 INVALID_DURATION (fuori dai 1-120 minuti), 400 TEST_TOKEN_RESTRICTED (funzione non disponibile su token di test — passa a produzione), 401 UNAUTHORIZED (token revocato o scaduto), 402 INSUFFICIENT_CREDITS, 404 PODCAST_NOT_FOUND e 429 RATE_LIMITED (riduci il ritmo usando l’header Retry-After). Tutti gli errori condividono la stessa busta JSON con campi
code,messageedetailsopzionali.