Skip to main content
A custom destination is a channel that points at a URL you own rather than at a social network. Ocoya POSTs each scheduled post to it as JSON, and your code decides what publishing means — an article in your CMS, a row in a database, a message on a queue. This page is the contract your endpoint has to satisfy. For the full request body, see Custom (webhook) in the help center.
Custom destinations are connected in the Ocoya app — Channels → Connect channel → Custom. There is no REST or MCP endpoint that connects one, so this page describes the endpoint you write, not one you call.

What Ocoya sends

A POST with a JSON body and Content-Type: application/json, plus any headers you configured on the channel.

What your endpoint must reply

Three things, all required. A publish missing any of them is recorded as failed.

1. A 2xx status

Anything else is recorded as a failed publish, and the status and response body are shown on the post so you can see what your endpoint said.

2. An id

Your own identifier for what you just created — a database row id, a CMS document id, whatever you would look the record up by. Ocoya stores it and sends it back to your delete URL, so this is what you delete by.

3. A url

The address you published to. It becomes the post’s View post link in Ocoya.
These are the only two keys read from the reply, and both spellings are exact. permalink was accepted as a synonym for url in earlier versions and no longer is.
Both are read from this reply only. There is no callback to send them in afterwards, so an endpoint that queues the work has to know its id and address before it answers rather than after the work finishes.
If your endpoint answers 2xx without them, Ocoya records the publish as failed and says so on the post. The content may well exist at your destination at that point — the message says as much, because republishing blindly would create a second copy.

Timing

Your endpoint has 30 seconds to respond. Acknowledge the request first and do the slow work afterwards, rather than the other way round. A redirect is followed rather than treated as a failure, as long as the address it points at passes the same checks the original did. The method is kept, so your endpoint still receives a POST with the body. Three hops is the limit.

Deleting

If the channel has a delete URL, deleting a post in Ocoya sends a post.deleted request there carrying the id you returned when it published:
id is at the top level and on its own — the identifier you issued, with nothing to parse and no wrapper to reach through. The url you returned is not sent back: an endpoint deleting by its own id has no use for an address it already knows. Answer any 2xx. If the post is already gone on your side, 404 or 410 is recorded as already deleted rather than as a failure. The post is deleted in Ocoya either way.

Custom (webhook)

The full payload, headers, limits and common problems.