> ## Documentation Index
> Fetch the complete documentation index at: https://docs.postonce.to/llms.txt
> Use this file to discover all available pages before exploring further.

# Save RSS updates as drafts

> Create reviewable PostOnce drafts from feed items with the API or native Zapier action, using stable retry keys.

Save an article title and link as an inbox draft, then review it before publishing. This first workflow needs no destination accounts or media. Creating a draft does not schedule or publish a social post.

Use a PostOnce plan with API access and a dedicated [API key](/getting-started/authentication). Grant `posts:write` to create drafts and `posts:read` to retrieve them. The Zapier connection test also needs `accounts:read`. Keep the key in your client's private credential store, never in feed data or shared workflow fields.

## Choose a stable source key

Build one key from a fixed feed prefix and the item's immutable GUID, for example `rss-draft:product-news:article-42`. If the feed has no GUID, use its stable article URL. The full key must be a nonblank string of at most 200 characters. If your identifiers are longer, use a deterministic digest of the feed identity and GUID rather than truncating away uniqueness.

Keep that key for every retry of the same item. Do not use the current time, a random value, or a new key merely because a response was lost. A new article needs its own identity. Final content should be the article title, a line break, and its link.

## Create through the API

Send `POST https://postonce.to/api/public/v1/drafts` with your private Bearer credential, JSON content, and the source key in the `Idempotency-Key` header. The header is optional in the API but should always be supplied for this automated workflow.

Example request body:

```json theme={null}
{
  "content": "Our latest product update\nhttps://example.com/news/article-42"
}
```

Example headers, with the credential value supplied privately by your client:

```text theme={null}
Content-Type: application/json
Idempotency-Key: rss-draft:product-news:article-42
Authorization: Bearer <your-private-api-key>
```

Read `data.id` from the creation response and store it with the source item. A successful first create returns HTTP 201 and a draft whose status is `inbox`. Retrieve that exact draft with `GET https://postonce.to/api/public/v1/drafts/{id}`, substituting the returned ID. Do not guess an ID or create another draft just to inspect the result.

Review it in [PostOnce drafts](https://postonce.to/dashboard/posts/drafts). If adding optional destinations through the API later, use `selected_account_ids` with actual connected account UUIDs. Saving those selections still does not publish.

## Use native Zapier actions

The [private PostOnce invitation](https://zapier.com/developer/public-invite/246101/073073858af32d4ba9fd68ec7877dc8f/) enables the native app in your Zapier account. It is not a public-directory approval or an importable Zap template.

1. Choose **RSS by Zapier → New Item in Feed**, set your feed URL, and test the trigger to load an actual item.
2. Add **PostOnce → Create Draft**. Save your API key in the private PostOnce connection's **API Key** field.
3. Map **Source Event Key** to `rss-draft:your-feed:` followed by the item's GUID, or a stable article URL when no GUID exists. Keep the prefix fixed and the complete string within 200 characters.
4. Map **Final Content** to the title, a line break, and the article link. Leave destination accounts and media empty for this first draft.
5. Test the action and inspect its returned `id` and `inbox` status. Optionally add **Find Draft by ID**, mapping the actual ID from Create Draft. Native Zapier actions expose the resource fields directly, while raw REST responses wrap them in `data`.

Review the saved draft before deciding whether to enable your Zap. Testing the workflow does not turn it on. Once intentionally enabled, inspect Zapier history to confirm incoming items produce the expected drafts. Keep the key out of ordinary action inputs, RSS fields, and shared screenshots.

## Retry without duplicating

Reuse the same key, credential, and unchanged JSON body. A matching replay returns the saved result. Deduplication is scoped to the PostOnce profile, API-key identity, endpoint, method, and key; rotating the API key changes that scope. Inspect earlier drafts before replaying old events with a new credential.

* `409 idempotency_key_reused`: the key was used with different content. Inspect the earlier result and reconcile the change instead of inventing a fresh key to bypass the conflict.
* `409 idempotency_request_in_progress`: an earlier request is still being processed. Keep its identity while investigating or retrying; do not issue a competing write with a new key.
* A timeout or lost response is not proof that creation failed. Check a known returned ID, or retry with the original identity and body.
* `401`: reconnect or replace the invalid credential. `403`: check the required scopes and plan entitlement. Credential replacement does not preserve the old key's deduplication scope.

Review the [error format](/getting-started/errors) and [rate limits](/getting-started/rate-limits). In Zapier, let native throttling retain the original mapped input rather than adding a second write loop.

## Choose accounts and media for later actions

`GET https://postonce.to/api/public/v1/accounts` requires `accounts:read` and returns accounts in `data`. Each account includes `id`, `platform`, `media_requirements`, and `capabilities` (which can be null). There is no separate capabilities endpoint in this API.

| Field                                         | How to use it                                                                              |
| --------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `capabilities.destination`                    | Must be `true` when choosing a publishing destination.                                     |
| `capabilities.source`                         | Must be `true` when choosing a crossposting source.                                        |
| `capabilities.text`, `images`, `video`        | Check support for the content you intend to send.                                          |
| `capabilities.replies`, `threads`, `backfill` | Check the relevant feature before requesting it; do not assume every platform supports it. |
| `capabilities.connection_mode`                | Describes the account's platform connection mode.                                          |
| `media_requirements`                          | Inspect the current platform-specific media constraints before preparing a file or URL.    |

An empty account list is a valid authenticated response and does not prevent creating the text-only draft above. Do not treat the first social account as the identity of the connected PostOnce profile. Use the returned account IDs and capability booleans when selecting destinations later; missing or null capabilities do not establish support.

A public media URL must meet the selected platform's requirements. For a local file, use the documented media upload operations, actually upload the bytes to the signed URL, then resolve the asset's `public_url`. Do not send the PostOnce Bearer key to a signed storage URL or treat a local path as uploaded media. See the Media API reference in the sidebar. Publishing is a separate action; a queued post is still waiting for delivery.
