---
title: "Publish"
description: "Enqueue a unified publish job, cancel a scheduled one, and read the delivery history."
section: "API reference"
url: https://dravo.dev/docs/api/publish
---
# Publish

The publish resource is the core of Dravo. You enqueue a job against one or more
connected accounts and Dravo delivers asynchronously. For the model behind these
calls, read [async publishing](/docs/concepts/async-publishing).

## Publish a post

Send the target accounts and the content. Returns `202` with a job id; the
post is delivered in the background.

#### `POST /v1/publish`

Enqueue a unified publish job to one or more connected accounts. Returns immediately (202) and delivers asynchronously.

**Auth:** API key (`dra_…`) or dashboard JWT

| Field | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `account_ids` | body | string[] | yes | 1 to 100 connected account IDs to publish to. |
| `text` | body | string | yes | Post body, 1 to 5000 chars. |
| `media_urls` | body | string[] | no | Public URLs of images/videos, ideally ingested first via POST /v1/media. |
| `provider_options` | body | object | no | Per-provider overrides keyed by provider (e.g. tiktok.privacy_level). |
| `scheduled_at` | body | string (ISO 8601) | no | If set, schedule the job. Must be timezone-aware and at least 60 seconds in the future. |

Request:

```json
{
  "account_ids": [
    "acc_8f2c1d",
    "acc_4b9e07"
  ],
  "text": "Shipping Dravo: one API for every social network.",
  "media_urls": [
    "https://cdn.dravo.dev/u/abc/cover.jpg"
  ],
  "provider_options": {
    "tiktok": {
      "privacy_level": "SELF_ONLY"
    }
  }
}
```

Response `202`: Job accepted and queued (or scheduled).

```json
{
  "job_id": "job_2a7f93",
  "status": "queued",
  "scheduled_at": null
}
```

Errors:

- `400`: Validation error (empty text, no account_ids, scheduled_at in the past).
- `401`: Missing or invalid API key / JWT.


## Cancel a scheduled job

Cancel a job while it is still `scheduled`. Once it has queued for delivery it
can no longer be canceled.

#### `POST /v1/publish/{job_id}/cancel`

Cancel a scheduled job that has not yet been queued for delivery.

**Auth:** API key (`dra_…`) or dashboard JWT

| Field | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `job_id` | path | string | yes | The job to cancel. |

Response `200`: Job canceled.

```json
{
  "job_id": "job_2a7f93",
  "status": "canceled",
  "scheduled_at": "2026-07-01T09:00:00Z"
}
```

Errors:

- `409`: Job already queued/processing and can no longer be canceled.
- `404`: Job not found.


## List publish history

Paginated history with the per account delivery results, filterable by status,
provider and free text.

#### `GET /v1/publish`

Paginated history of publish jobs with per-account delivery results.

**Auth:** API key (`dra_…`) or dashboard JWT

| Field | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `status` | query | string | no | Filter: queued, processing, published, partial, failed, canceled, scheduled. |
| `provider` | query | string | no | Filter by provider. |
| `q` | query | string | no | Full-text search on post text. |
| `limit` | query | int | no | Page size, 1 to 100 (default 50). |
| `cursor` | query | string | no | Keyset pagination cursor from next_cursor. |

Response `200`: A page of publish logs.

```json
{
  "items": [
    {
      "id": "log_19ab",
      "job_id": "job_2a7f93",
      "status": "published",
      "text": "Shipping Dravo…",
      "providers": [
        "x",
        "linkedin"
      ],
      "results": [
        {
          "provider": "x",
          "status": "published",
          "platform_post_id": "1890…"
        }
      ],
      "created_at": "2026-06-23T10:15:30Z"
    }
  ],
  "next_cursor": null,
  "total": 1
}
```
