Il canale Custom non pubblica su una rete. Invia ogni post programmato a un URL di tua proprietà, come JSON, e tutto ciò che succede dopo dipende dal tuo codice.
Usalo per un CMS a cui Ocoya non si collega, un generatore di siti statici, una coda di revisione interna o qualsiasi cosa preferisci costruire invece di aspettare.
Collegare un endpoint

Il modulo di connessione. Il pannello accanto ai campi è il contratto di risposta: un 2xx e l’indirizzo a cui collegarsi.
Apri Channels
Seleziona Channels nella barra laterale sinistra, poi Connect channel.
Scegli Custom
Scegli Custom dal pannello Add a connection.
Dagli un nome
Dagli un nome che riconoscerai nell’elenco dei canali, come Il mio blog. È solo un’etichetta.
Inserisci il tuo publish URL
L’URL completo, schema incluso: https://example.com/hooks/content. Deve essere raggiungibile dai server di Ocoya, quindi un indirizzo sul tuo computer o all’interno di una rete privata non funziona.
Se il tuo sito fa un reindirizzamento (da example.com a www.example.com, o da http a https) vanno bene entrambe le forme. Ocoya segue il reindirizzamento dopo aver controllato il nuovo indirizzo come ha controllato il primo.
Facoltativo: aggiungi un delete URL
Sotto Advanced options. Un secondo indirizzo, usato quando un post viene eliminato in Ocoya: https://example.com/hooks/content/delete. Se lo lasci vuoto, eliminare un post in Ocoya lo lascia dov’è stato pubblicato.
Deve essere un URL diverso da quello sopra. Il tuo endpoint di pubblicazione crea qualcosa con POST; se l’eliminazione andasse nello stesso posto, creerebbe una seconda copia su qualsiasi ricevente che non controlla il nome dell’evento.
Facoltativo: aggiungi degli header
Anche questi sotto Advanced options. La maggior parte degli endpoint vuole sapere che la richiesta è tua prima di accettarla: aggiungi Authorization con valore Bearer your-token, o qualunque header controlli il tuo ricevente. Ognuno viene inviato con ogni richiesta, a entrambi gli URL.
Senza un header di autorizzazione, l’URL è l’unica credenziale: chiunque lo scopra può inviare post al tuo endpoint. Aggiungine uno o, come minimo, usa un percorso lungo e impossibile da indovinare.
I valori degli header vengono conservati come le credenziali e non vengono mai rimandati al browser, quindi il modulo di connessione mostra una sezione Headers vuota anche per una destinazione che ne ha. Ricollegare lo stesso URL sostituisce l’intero insieme: reinserisci ogni header che vuoi mantenere.
Cosa riceve il tuo endpoint
Una POST con Content-Type: application/json. Contiene ciò che serve a un blog e nient’altro:
{
"event": "post.published",
"publishedAt": "2026-09-17T09:00:00.000Z",
"post": {
"id": "clx…",
"title": "Three labels, one warmer palette",
"caption": "Testing a softer set of creams…",
"image": "https://…/image.jpg"
}
}| Campo | Cos’è |
|---|---|
post.id | L’id di Ocoya per questo post. Resta lo stesso se una consegna viene ritentata, quindi usalo come chiave per aggiornare invece di pubblicare una seconda copia |
post.title | Il titolo, oppure null se non ne è stato impostato uno |
post.caption | Il corpo, esattamente come è stato scritto. Markdown se hai scritto in Markdown |
post.image | La prima immagine del post, come URL da scaricare: scaricala, non fare hotlinking. null se non ce ne sono. I video non vengono inviati |
post.options | Campi dell’articolo, quando il post ne ha. Elencati più sotto |
Dentro post.options
Li hanno solo gli articoli, cioè quelli scritti da una campagna blog. Un post pubblicato a mano non ne ha e options viene omesso del tutto. Tratta ogni campo come facoltativo.
| Campo | Tipo | Cos’è |
|---|---|---|
markdownMode | boolean | true quando post.caption è Markdown. Renderizzalo di conseguenza |
slug | string | Uno slug adatto agli URL ricavato dal titolo: why-your-content-is-not-converting. Sta a te usarlo o ignorarlo |
excerpt | string | Un riassunto di una o due frasi, per una card o un feed |
seoTitle | string | Fino a 70 caratteri, per <title> |
seoDescription | string | Fino a 200 caratteri, per <meta name="description"> |
tags | string[] | Tag dell’articolo. Di solito uno |
readingMinutes | number | Calcolato dal corpo finito |
Un articolo arriva così:
{
"event": "post.published",
"publishedAt": "2026-09-22T09:00:00.000Z",
"post": {
"id": "clx…",
"title": "Why your content is not converting",
"caption": "You're posting every day and still refreshing an empty inbox.\n\n## The three pillars\n\n- A clear offer, repeated\n- One place to send people\n",
"image": "https://…/cover.png",
"options": {
"markdownMode": true,
"slug": "why-your-content-is-not-converting",
"excerpt": "Volume is rarely the problem. Nothing you publish asks anybody to do anything.",
"seoTitle": "Why your content is not converting",
"seoDescription": "Volume is rarely the problem. Here is the system that fixes it.",
"tags": ["content-marketing"],
"readingMinutes": 7
}
}
}post.caption è Markdown quando markdownMode è true. Pubblicarlo senza renderizzarlo mette sul tuo sito ## The three pillars così com’è scritto, ed è esattamente l’effetto che fa.
Ti serve qualcosa che non c’è? Dicci. I campi vengono aggiunti quando un ricevente ne ha bisogno, non inviati per ogni evenienza.
Eliminare un post
Eliminare un post in Ocoya lo elimina sulle reti su cui è andato. Una destinazione custom è il tuo sistema, quindi Ocoya può solo avvisarla, cosa che fa con una POST al delete URL, se ne hai indicato uno.
Il corpo è di nuovo il post pubblicato, con tre aggiunte: il nome dell’evento, i timestamp e, unico campo che ti serve, l’id che il tuo endpoint ha restituito quando ha pubblicato.
{
"event": "post.deleted",
"id": "9f2c1a",
"publishedAt": "2026-09-22T09:00:00.000Z",
"deletedAt": "2026-09-28T14:12:00.000Z",
"post": {
"id": "clx…",
"title": "Why your content is not converting",
"caption": "…",
"image": null,
"options": { "slug": "why-your-content-is-not-converting" }
}
}Elimina tramite id: l’identificatore che il tuo endpoint ha restituito alla pubblicazione, rimandato così com’è al livello principale, così non c’è nulla da estrarre da un indirizzo. L’url che hai restituito non viene inviato: un endpoint che elimina con il proprio id non ha bisogno di un indirizzo che già conosce.
Senza un delete URL configurato non viene inviato nulla. Il post viene eliminato in Ocoya e il canale segnala che la sua copia è ancora online, invece di non fare nulla in silenzio.
Rispondi con un qualsiasi 2xx, come per una pubblicazione. Se il post non esiste già più dalla tua parte, rispondi 404 o 410 e Ocoya lo registra come già eliminato invece che come un errore. Qualsiasi altra risposta viene segnalata sul post, e il post viene comunque eliminato in Ocoya: una destinazione che rifiuta non è mai un motivo per tenere un post che hai chiesto di eliminare.
Cosa si aspetta Ocoya in risposta
Rispondi con uno stato 2xx qualsiasi. Qualsiasi altra cosa viene registrata come pubblicazione non riuscita, e lo stato e il corpo della risposta vengono mostrati sul post, così puoi vedere cosa ha detto il tuo endpoint.
Restituisci un id e un url
Il tuo endpoint deve rispondere con entrambi, come JSON:
{
"id": "9f2c1a",
"url": "https://yourblog.com/post"
}| Campo | Cos’è | Cosa ne fa Ocoya |
|---|---|---|
id | Un tuo identificatore per ciò che hai appena creato: l’id di una riga, l’id di un documento | Lo rimanda al tuo delete URL come id. È ciò con cui elimini. |
url | L’indirizzo su cui hai pubblicato | Diventa il link View post del post |
Sono richiesti entrambi. Un 2xx senza di essi viene registrato come pubblicazione non riuscita, e il messaggio sul post lo dice, precisando anche che il contenuto potrebbe già esistere nella tua destinazione, quindi ripubblicare alla cieca creerebbe una seconda copia.
url è l’unica chiave letta per l’indirizzo: permalink era accettato come sinonimo nelle versioni precedenti e ora non lo è più.
Restituisci entrambi nella stessa risposta. Ocoya li legge una volta sola, quando il tuo endpoint risponde; non esiste una callback in cui inviarli dopo, quindi un endpoint che mette il lavoro in coda deve conoscere il proprio id e il proprio indirizzo finale prima di rispondere, non dopo.
Il tuo endpoint ha 30 secondi per rispondere. Fai il lavoro lento dopo aver risposto, non prima: conferma la richiesta, poi elaborala.
Un reindirizzamento viene seguito invece di essere trattato come un errore, purché l’indirizzo a cui punta superi lo stesso controllo dell’originale: raggiungibile pubblicamente e vincolato a ciò a cui si risolve. Il metodo viene mantenuto, quindi il tuo endpoint riceve comunque una POST con il corpo. Il limite è tre passaggi.
Limiti
| Titolo | 300 caratteri |
| Corpo | 200.000 caratteri |
| Media | 20 elementi |
| Timeout | 30 secondi |
| Header | Fino a 10, con valori di 2.000 caratteri |
Dietro un webhook non c’è nessun fornitore, quindi non c’è nulla di reale con cui validare: il lato ricevente è tuo e decidi tu cosa accetta. Sono guardrail più che limiti: abbastanza ampi per un articolo lungo con i suoi media, abbastanza stretti da fermare una generazione fuori controllo nel composer invece che al tuo endpoint.
Problemi comuni
“A destination URL must start with http:// or https://.” All’URL manca lo schema. Includilo.
“”Content-Type” is set by Ocoya and cannot be overridden.” Alcuni header descrivono la richiesta stessa invece di autenticarla: gli header del contenuto, Host, Connection, Transfer-Encoding. Li imposta Ocoya, quindi i tuoi header non possono sostituirli.
“”…” is not a valid header name.” Un nome di header è fatto di lettere, cifre e trattini. Uno spazio o i due punti nel campo del nome di solito significano che è stata incollata l’intera riga Name: value: il nome va nel campo a sinistra, il valore in quello a destra.
“That is not a valid URL.” L’indirizzo non è stato interpretato. Controlla errori di battitura e spazi superflui.
“Your endpoint could not be reached. Check the URL is correct and publicly accessible.” Il DNS non si è risolto o la connessione è stata rifiutata. Un endpoint su localhost o in una rete privata non è raggiungibile da Ocoya.
“Your endpoint answered 200 but did not return id or url.” La richiesta è arrivata al tuo endpoint e lui l’ha accettata, ma nella risposta mancavano uno o entrambi i campi richiesti. Ocoya lo registra come pubblicazione non riuscita perché senza un id non c’è nulla con cui eliminare in seguito.
Tieni presente che il contenuto potrebbe già esistere nella tua destinazione: l’endpoint ha risposto con successo. Controlla prima di ripubblicare, o ti ritroverai con due copie.
“This destination has no delete endpoint.” Un post è stato eliminato in Ocoya e questo canale non ha un delete URL, quindi non è stato inviato nulla e la copia nella tua destinazione è ancora lì. Ricollega la destinazione con un delete URL per cambiare la cosa.
“Your endpoint did not respond in time.” Ci ha messo più di 30 secondi. Conferma prima, elabora dopo.
“Your endpoint redirected to https://…” Il reindirizzamento è uscito dall’indirizzo che hai indicato: un host diverso o uno schema diverso che Ocoya non poteva ricontrollare, oppure uno che si risolveva in un indirizzo privato. Usa l’indirizzo che risponde direttamente. Un reindirizzamento che resta su un indirizzo raggiungibile pubblicamente viene seguito per te, fino a tre passaggi.
“Your endpoint returned 500: …” Il tuo codice ha generato un errore. Il dettaglio dopo lo stato è ciò che il tuo endpoint ha rimandato indietro, troncato.