Pillar 1 of 3
One request, fanned out to every connected account. Media requirements, character limits and threading rules are normalised before the request reaches a platform.
Live on 17 networksThe model
Publishing is built around two ideas:Accounts, not networks
You address a post to connected account ids. Nylon already knows which network each one belongs to and what that network accepts.
One payload, many targets
The same content object is adapted per target rather than being written per target by you.
What gets normalised for you
Validated before anything sends
A post addressed to five profiles is checked against all five before the first upload starts. If it is invalid anywhere, nothing publishes and the response names the network and the rule. That is a deliberate trade: a post that lands on four of five targets is worse than one that is refused, because you have already been told it worked and have to discover the rest later.POST /v1/validate runs the same check without publishing, and GET /v1/networks hands you the same limits table the validator uses, so you can check a caption client-side and get the same answer.
Synchronous by design
POST /v1/posts returns once every target has been attempted. The response carries the network post ids, the permalinks and any per-target error — not a job id to poll.
A carousel to Instagram plus a video to LinkedIn is minutes of upload, so allow a generous client timeout. Send an idempotency_key and a retry after a timeout returns the original post rather than publishing it twice.
Threading
Four networks publish a long caption as a chain of replies: X, Threads, Bluesky and Mastodon.textmay exceed one post’s limit on those networks. Withauto_thread(the default) Nylon splits it on sentence boundaries.- Send
threadinstead and the parts are published verbatim — someone who wrote the breaks gets the breaks they wrote. - On the other eight networks, a caption over the limit is an error rather than a thread.
GET /v1/networks reports both numbers per network: text.per_post is one post’s ceiling, text.max is the whole request’s.
Per-network overrides
When one network needs something different, override it by key. Everything you do not override falls back to the base payload.text, title, media, thread, post_type — replace the base values for that network. Every other key is a network option passed to the publisher; options in GET /v1/networks lists what each one reads. An unknown network key is rejected by name rather than ignored.
Scheduling
Sendscheduled_at and the post is stored and published by Nylon at that time — a durable run holds the post and wakes at its time, so the post goes out at the minute you asked for rather than on the next sweep of a queue. A time in the past is treated as now rather than refused — a caller catching up on a queue means “as soon as possible”, not “reject this” — and so is a time less than a minute out, because “in forty seconds” means now. The response tells you which happened: a scheduled post comes back with status: "scheduled" and the time it will go out, and an immediate one comes back already published.
A scheduled post can be edited with PATCH /v1/posts/{postId} or stopped with DELETE /v1/posts/{postId}. Content fields are replaced, not merged: sending text alone means “this is the text now”.
Partial failure and retries
A post can succeed on one network and fail on another. That is not an error response — the post exists withstatus: "partially_published", and each target carries its own status and error.
Media that is too large
Nylon fixes weight, never shape. An image over a network’s byte limit is recompressed before upload — the quality is stepped down first, then the dimensions, until it fits. The picture is the same picture, so nothing about your post changes except its file size. A transparent PNG stays a PNG; an opaque one may become a JPEG, which is where most of the saving comes from. Everything else is refused with the real numbers, because fixing it would mean changing what you published:- Aspect ratio and exact dimensions. Cropping to fit Instagram’s feed range, or to Dribbble’s 400x300, throws away part of the image you chose.
- Video. It is never re-encoded. A video over the limit comes back as
media_errorsaying so. - Animated GIFs. Re-encoding an animation frame by frame produces a different animation.
POST /v1/validate reports every one of these before anything publishes, and GET /v1/networks hands you the same byte limits the compressor works to.
POST /v1/posts/{postId}/retry republishes what did not go out — the targets that failed, and any a run that died mid-flight never reached. Targets that already published are never included, whatever the request asks for: double-posting is the one failure a customer cannot undo. A post still waiting for its scheduled time cannot be retried, because that would send it early rather than recover anything.
Supported networks
Publishing is live on all seventeen networks listed on the Connections page. Capabilities vary by network and account type — a Facebook Page accepts Reels, an X handle accepts threads — and the per-network detail is listed there and inGET /v1/networks.
Endpoints
Create a post
POST /v1/postsValidate a post
POST /v1/validateList posts
GET /v1/postsRetrieve a post
GET /v1/posts/{postId}Update a scheduled post
PATCH /v1/posts/{postId}Retry failed targets
POST /v1/posts/{postId}/retryConnections
Understand connected profiles and connection statuses before you publish to them.