Publish content

Create posts and other provider content with Koil Publish Requests.

Use Publish Requests to create provider content through a Connected Profile. Koil validates the request, runs the provider operation, and gives you one status to track.

Start here after you have a connectedProfileId from Connect provider accounts.

How it works

  1. Check what the Connected Profile can publish. GET /v1/connected-profiles/{connectedProfileId}/capabilities

  2. Choose a supported contentType and, when required, a variant.

  3. Upload or stage media if the publish schema requires it. POST /v1/media

  4. Submit one or more publish items. POST /v1/publish-requests

  5. Store each returned publish request ID and status URL.

  6. Read status until the request settles: succeeded, failed, cancelled, or outcome_unknown. GET /v1/publish-requests/{publishRequestId}

To change scheduled work, cancel it before it runs and submit a new request. POST /v1/publish-requests/{publishRequestId}/cancel

Example

curl -X POST "https://api.koil.co/v1/publish-requests" \  -H "Authorization: Bearer $KOIL_API_KEY" \  -H "Content-Type: application/json" \  -H "Idempotency-Key: $(uuidgen)" \  -d '{  "publishRequests": [    {      "contentType": "instagram.media.items",      "variant": "feed",      "connectedProfileId": "cp_123",      "groupId": "campaign-42",      "clientItemId": "draft-1",      "args": {        "text": "Hello world",        "media": [          {            "mediaId": "med_123",            "altText": "A cat"          }        ],        "scheduling": {          "at": "2026-05-01T10:00:00Z"        }      }    }  ]}'

What goes in args depends on the content type and variant: each provider page lists the args of every publish, per variant.

Koil validates contentType, variant, and args before anything is sent to the provider. If one item in a batch is invalid, the batch is rejected with every problem named, and nothing runs.

Media Inputs

Use mediaId for images, videos, and other assets whenever possible. Koil can stage, validate, and reuse the media before the provider request runs.

Some publish schemas also accept sourceUrl. Use HTTPS URLs only.

Every asset, uploaded or fetched from a sourceUrl, must fit these limits; each destination may add its own format, dimension, and duration requirements.

LimitValue
Image file size50 MB
Image dimensions (width × height)100 megapixels
Video file size1 GB
mediaId accepted by publish requests24 hours after creation

An asset over a size limit fails processing, and its media object reports failed. A publish request that references a mediaId created more than 24 hours earlier is rejected with validation_error (violation media_expired at that media item's path): create the media again and reference the new mediaId. A publish scheduled for later only needs its media to be fresh when you submit it.

Batches and retries

POST /v1/publish-requests accepts up to 100 items or a 1 MB body, whichever is lower. Koil validates the request first, then runs accepted items independently.

Use groupId to connect related items, such as a campaign. Use clientItemId to map each Koil item back to a draft or record in your system.

Send an Idempotency-Key header when submitting publish requests. Koil requires it and dedupes the whole submit operation:

  • Reusing the same key and payload returns the same accepted result after the first submission resolves.
  • Reusing the same key with a different payload returns 409 conflict.
  • To retry failed items, submit only those items with a new idempotency key.
  • A request that died before answering (a timeout, a dropped connection) is safe to retry with the same key and payload: the retry resumes it, and items it already accepted keep their publishRequestId and are not published again. While the first attempt may still be running (up to 15 minutes), the retry answers 409 conflict.

When a publish fails

A failed publish carries an error in the same shape as an API error (code, message, meta), on the request and on its publish_request.failed event. A provider refusal names its reason, such as validation_error with the provider's message; an internal error keeps no message. A failed request published nothing: fix the cause and submit it again with a new Idempotency-Key.

outcome_unknown means the call that creates the content failed ambiguously: it timed out, the connection dropped, or the provider answered with a server error. The provider may have published it. Koil never retries that call, because providers offer no way to make it safe to repeat. Check the provider (the profile's recent posts or comments) before submitting again, or the content may appear twice.

What not to send

Use Koil fields in args. Do not send raw provider payloads or provider OAuth credentials.

On this page