diff --git a/docs.json b/docs.json index 169b249..9350aba 100644 --- a/docs.json +++ b/docs.json @@ -217,15 +217,6 @@ "knowledge-base/analytics" ] }, - { - "group": "Automations", - "pages": [ - "knowledge-base/automations/introduction", - "knowledge-base/automations/triggers-and-nodes", - "knowledge-base/automations/variables", - "knowledge-base/automations/monitoring" - ] - }, { "group": "Accounts", "pages": [ diff --git a/knowledge-base/automations/introduction.mdx b/knowledge-base/automations/introduction.mdx deleted file mode 100644 index e6cf6d0..0000000 --- a/knowledge-base/automations/introduction.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "Automations" -description: "Build flows that fetch, generate, and publish content on autopilot" -icon: "bolt" ---- - - - Automations are in **beta**. The building blocks below are stable, but expect new node types and refinements over time. - - -Automations let you wire together a **flow** that runs on its own: a trigger starts it, action nodes fetch data and generate content, and output nodes publish posts or call webhooks. Think of it as a visual pipeline for content that would otherwise be manual. - -A few things you can build: - -- Turn a blog or news **RSS feed** into a daily AI-written post. -- React whenever you **publish a post** and notify an external service. -- Pull data from any **HTTP API** and generate a post from it on a schedule. - -## How a flow works - -Every automation is a graph of **nodes** connected by lines: - - - - A schedule, or a post being published or scheduled. There is exactly one trigger per automation. - - - Fetch an RSS feed or HTTP endpoint, generate content with AI, branch on a condition, or wait. - - - Publish the generated post, or send an HTTP request from a [Webhook node](/knowledge-base/automations/triggers-and-nodes#output-nodes). For signed post-lifecycle notifications outside a flow, use [workspace webhooks](/knowledge-base/webhooks). - - - -Data flows **downstream**: each node can use the data produced by the nodes connected before it. See [Variables and expressions](/knowledge-base/automations/variables) for the full picture. - -## The editor - -Open an automation to land in the **Workflow** editor — a canvas where you drag nodes from the sidebar and connect them. Click any node to open its settings in that same panel. - -The detail screen has four tabs: - - - - The visual editor where you build and save the flow. - - - A log of every real run, with per-node detail. See [Monitoring](/knowledge-base/automations/monitoring). - - - Run health and output charts over a date range. - - - Rename, activate or pause, and delete the automation. - - - -## Build your first automation - - - - Go to **Automations** and click **New automation**. It opens in the Workflow editor with a schedule trigger already in place. - - - Click the trigger node and pick when it fires — a schedule, or a post event. See [Triggers and nodes](/knowledge-base/automations/triggers-and-nodes). - - - Drag nodes from the sidebar onto the canvas and connect them by dragging from one node's handle to the next. - - - In any text field, type `{{` to autocomplete the data available at that point in the flow. - - - Click **Run test** to execute the flow end-to-end with synthesized data before going live. - - - Click **Save**, then open the **Settings** tab and flip the status switch to activate. The automation now runs on its own. - - - -## Statuses - -An automation is always in one of three states: - -| Status | Meaning | -| --- | --- | -| **Draft** | Being built. It never runs. | -| **Active** | Live. The trigger fires and the flow runs. | -| **Paused** | Stopped. The trigger no longer fires until you reactivate it. | - - - Activating and pausing live in the **Settings** tab. You can pause anytime without losing your flow. - diff --git a/knowledge-base/automations/monitoring.mdx b/knowledge-base/automations/monitoring.mdx deleted file mode 100644 index 0c99f3a..0000000 --- a/knowledge-base/automations/monitoring.mdx +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: "Testing and monitoring" -description: "Test runs, the invocations log, metrics, and lifecycle settings" -icon: "chart-line" ---- - -Once a flow is built, you can test it before going live and watch how it performs once it's running. - -## Testing - -Click **Run test** in the Workflow editor to execute the whole flow end-to-end and inspect what each node does. The result panel shows every node's **input** and **output** as it runs — the fastest way to confirm your expressions resolve correctly. - -There are two modes: - -| Mode | What it does | -| --- | --- | -| **Dry run** (default) | Runs every node, including AI generation, but **never publishes** a post or triggers external side effects. The generated content is shown but not saved. | -| **With real data** | Actually publishes posts and fires webhooks. Use it for a final end-to-end check. | - - - A **With real data** test really publishes and fires side effects. Use it deliberately. - - - - Test runs never appear in the Invocations log or Metrics — those report only on real, automatic executions. - - -## Invocations - -The **Invocations** tab is the run log: every time the live automation fires, it lands here, newest first. - -Each row shows: - -- **Timestamp** — when the run started -- **Run** — its ID (click to copy) -- **Status** — completed, failed, running, waiting, pending, or cancelled -- **Last message** — a summary and the number of steps it ran -- **Duration** — how long it took - -Click any row to expand it and see the **per-node breakdown** of that run. Use the **status filter** to narrow to failures, and the **search** box to find a run by ID. - - - Only real executions show up here. Tests you run from the editor are kept out so the log stays meaningful. - - -## Metrics - -The **Metrics** tab charts the automation's health and output over a date range you pick with the range picker. - -**Run health** - -- Total runs, completed, failed, in progress -- Success rate and average duration -- A chart of runs started, completed, and failed over time - -**Output** - -- Posts created by the automation -- A breakdown of those posts by platform - - - Like Invocations, Metrics count only real runs — test runs never inflate the numbers. - - -## Settings and lifecycle - -The **Settings** tab is where you operate the automation: - - - - Change the automation's name without touching the flow. - - - Flip the status switch to go live or stop. Pausing keeps the flow intact — the trigger simply stops firing until you reactivate. - - - In the **danger zone**, permanently remove the automation and its run history. This can't be undone. - - - -## Related - - - - The big picture and a build walkthrough. - - - Pass data between nodes. - - diff --git a/knowledge-base/automations/triggers-and-nodes.mdx b/knowledge-base/automations/triggers-and-nodes.mdx deleted file mode 100644 index 29433e0..0000000 --- a/knowledge-base/automations/triggers-and-nodes.mdx +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: "Triggers and nodes" -description: "Every building block you can drop into a flow" -icon: "diagram-project" ---- - -A flow is built from **nodes**. One trigger starts it; the rest fetch data, shape the flow, or deliver output. Drag nodes from the editor sidebar and connect them by dragging from a node's handle to the next node. - -## Triggers - -Every automation has exactly one trigger. It decides **when** the flow runs. - -| Trigger | Fires when | Provides | -| --- | --- | --- | -| **Schedule** | A cron-style schedule you set (every N minutes/hours/days, weekly, monthly, or a custom expression) | `trigger.event`, `trigger.fired_at` | -| **Post published** | One of your posts is published | `trigger.post.*` | -| **Post scheduled** | One of your posts is scheduled | `trigger.post.*` | - - - The trigger is created with the automation and can't be removed — you can only change its type. The schedule editor lets you pick an interval, time, weekdays, or a custom cron expression, and the timezone defaults to your workspace timezone. - - -## Source nodes - -Source nodes pull external data into the flow. Both expose two output handles — **has items** and **no items** — so you can branch on whether anything new came back. - - - - Reads an RSS/Atom feed from a **Feed URL** and exposes the matched item as `fetched.title`, `fetched.link`, `fetched.description`, and `fetched.pubDate`. - - TryPost remembers which items it has already seen, so the flow only runs for genuinely **new** entries. - - - Calls any HTTP endpoint. Configure the **URL**, **method** (GET/POST/PUT/PATCH/DELETE), authentication (none, bearer, basic, or API key), headers, and a body template. Auth tokens and passwords are stored encrypted. - - The JSON response becomes `fetched`, so you reference any field with `{{ fetched. }}`. Optional **items path**, **item key path**, and **item date path** settings let it walk a list response and dedupe items the same way the RSS node does. - - - - - **First run sets a baseline.** The first time a source node polls an existing feed or endpoint, it records what's already there and produces nothing — only items that appear *after* that trigger the flow. - - **New items fan out.** When a source node then finds several new items at once, each one runs the downstream nodes independently — five new feed entries produce five posts. A test run only ever processes the first item, so it stays predictable. - - -## Content node - - - Generates a post with AI and attaches it to one or more social accounts. - - - **Accounts** — which connected accounts and content types to post to. The most restrictive selected platform (smallest character limit) drives the generated copy so it fits everywhere. - - **Prompt** — your instruction. Reference upstream data with `{{ }}`, e.g. `Write a post about {{ fetched.title }}`. - - **Image count** — `0` for text-only (LinkedIn, X, Threads), `1` for a single image, or `2–10` for a carousel. The picker only offers counts the selected accounts support. - - **Use brand voice** — when off, the post stays faithful to the source instead of being rewritten in your brand persona. Useful for news curation. - - **Use brand visuals** — when off, generated images skip your brand colors and identity. - - Provides `generated.content` and `generated.post_url`. - - - - The Generate node uses the same content engine as **Create with AI** — see [AI features](/knowledge-base/ai-features) and [Brand profile](/knowledge-base/brand-profile). - - -## Flow nodes - -These shape the path the run takes. - - - - Branches the flow. Compares a **field** (any `{{ }}` expression) against a **value** using one of: `contains`, `not contains`, `equals`, `not equals`, `matches` (regex), `greater than`, or `less than`. The flow continues down the matching branch. - - - Pauses the flow for a **duration** in minutes, hours, or days before continuing. Useful for spacing out actions. - - - -## Output nodes - - - - Publishes the post created by an upstream Generate node. Choose a **mode**: - - | Mode | Result | - | --- | --- | - | **Now** | Publishes immediately | - | **Scheduled** | Schedules it, offset by N minutes from now (default 60) | - | **Draft** | Leaves it as a draft for you to review | - - - Sends an HTTP request to an external system. Configure the **URL**, **method**, headers, and a **payload template** where you can inject any `{{ }}` expression. - - This is a one-off call inside the flow — not a workspace [event webhook](/knowledge-base/webhooks). Posts this flow creates still emit workspace webhook events if you subscribed (`created_via` is `automation`). Use workspace webhooks when you want signed `post.published` / `post.failed` deliveries for every matching post. - - - Stops the automation at that point. Optional — a branch ends on its own when it has no more nodes. - - - -## What's next - - - - Pass data between nodes with `{{ }}`. - - - Test runs, the invocations log, and metrics. - - diff --git a/knowledge-base/automations/variables.mdx b/knowledge-base/automations/variables.mdx deleted file mode 100644 index a3cc61b..0000000 --- a/knowledge-base/automations/variables.mdx +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: "Variables and expressions" -description: "Pass data between nodes with double-brace expressions and reusable workflow variables" -icon: "code" ---- - -Automations move data between nodes with **expressions**. Wrap a path in double braces and TryPost replaces it at run time with the real value: - -```text -Write a short post about {{ fetched.title }} and link to {{ fetched.link }}. -``` - -Expressions work in **any text field** of any node — prompts, webhook payloads, HTTP bodies, condition fields, and more. - -## What data is in scope - -This is the rule that trips people up most: - - - A node can only use data from nodes connected **before** it (upstream). If a node isn't on the path leading into the current node, its data isn't available. - - -So a Generate node placed after a **Fetch RSS** node can use `{{ fetched.title }}`, but a node that runs *before* the fetch cannot — the data doesn't exist yet at that point in the flow. - - - In any field, type `{{` to open an autocomplete of exactly what's in scope at that node. Known references are highlighted; unknown ones are flagged so you catch typos before running. - - -## Expression reference - -Which expressions exist depends on which nodes run upstream. - -### Schedule trigger - -Available when the flow starts from a **Schedule** trigger. - -| Expression | Value | -| --- | --- | -| `{{ trigger.event }}` | The trigger event name | -| `{{ trigger.fired_at }}` | When the trigger fired | - -### Post trigger - -Available when the flow starts from a **Post published** or **Post scheduled** trigger. - -| Expression | Value | -| --- | --- | -| `{{ trigger.post.id }}` | The triggering post's ID | -| `{{ trigger.post.content }}` | Its content | -| `{{ trigger.post.status }}` | Its status | -| `{{ trigger.post.scheduled_at }}` | When it's scheduled | -| `{{ trigger.post.published_at }}` | When it was published | - -### Fetch RSS - -Available downstream of a **Fetch RSS** node. - -| Expression | Value | -| --- | --- | -| `{{ fetched.title }}` | The feed item's title | -| `{{ fetched.link }}` | Its link | -| `{{ fetched.description }}` | Its description | -| `{{ fetched.pubDate }}` | Its publish date | - -### HTTP Request - -Available downstream of an **HTTP Request** node. The whole JSON response is exposed as `fetched`, so you append whatever path you need: - -```text -{{ fetched.data.0.title }} -{{ fetched.user.name }} -``` - -| Expression | Value | -| --- | --- | -| `{{ fetched. }}` | Any field from the JSON response | - -### Generate - -Available downstream of a **Generate** node. - -| Expression | Value | -| --- | --- | -| `{{ generated.content }}` | The AI-generated post content | -| `{{ generated.post_url }}` | The generated post's URL | - -### Always available - -These work anywhere in any flow. - -| Expression | Value | -| --- | --- | -| `{{ variables.YOUR_KEY }}` | A workflow variable (see below) | -| `{{ now }}` | The current date and time | - -## Workflow variables - -Workflow variables are **reusable values** you define once and reference anywhere with `{{ variables.KEY }}`. They're scoped to a single automation. - -Use them for values you repeat across nodes or want to keep out of node fields — API keys, base URLs, account handles, a default hashtag. - - - - In the Workflow editor, switch to the **Variables** tab in the right sidebar. - - - Give it a **key** (letters, numbers, and underscores — e.g. `API_KEY`) and a **value**. - - - Use `{{ variables.API_KEY }}` in any field, in any node. - - - - - Variable values are **stored encrypted**. They're safe for secrets like API keys. - - -## See it in action - -The surest way to learn what's available is to run the flow: - - - Click **Run test** in the editor and open the result panel. Each node shows its exact **input** and **output**, so you can see precisely what every expression resolves to. See [Testing and monitoring](/knowledge-base/automations/monitoring). - diff --git a/knowledge-base/plans-and-billing.mdx b/knowledge-base/plans-and-billing.mdx index f107422..87d32c8 100644 --- a/knowledge-base/plans-and-billing.mdx +++ b/knowledge-base/plans-and-billing.mdx @@ -18,7 +18,7 @@ TryPost Cloud has one plan, priced per workspace. Every feature is included on e | Social accounts | One account on each network (your social set) | | Team members | Unlimited, with roles and approvals | | AI credits | 2,500 per month, pooled across your account | -| Included | Calendar, AI Copilot, automations, MCP server, REST API, analytics, signatures, labels | +| Included | Calendar, AI Copilot, MCP server, REST API, analytics, signatures, labels | Pricing is localized in some regions (for example, **R$60 / month** in Brazil). See the [pricing page](https://trypost.it/pricing) for current rates. diff --git a/knowledge-base/social-accounts.mdx b/knowledge-base/social-accounts.mdx index 87df830..4d5f233 100644 --- a/knowledge-base/social-accounts.mdx +++ b/knowledge-base/social-accounts.mdx @@ -97,7 +97,7 @@ If any of these detects a disconnected or expired account, the workspace owner r ## Reconnecting an account -A card that needs attention shows a **Reconnect** button. Reconnecting refreshes that specific card — it keeps its posts, its scheduling history, and its place in your automations. It never creates a second card. +A card that needs attention shows a **Reconnect** button. Reconnecting refreshes that specific card — it keeps its posts and its scheduling history. It never creates a second card. Because it is tied to one card, you have to authorize **the same account** you are reconnecting: diff --git a/knowledge-base/webhooks.mdx b/knowledge-base/webhooks.mdx index 77c1010..00368bf 100644 --- a/knowledge-base/webhooks.mdx +++ b/knowledge-base/webhooks.mdx @@ -6,7 +6,7 @@ icon: "webhook" Workspace webhooks POST a signed JSON payload to a URL you control whenever a subscribed post event fires. Use them to sync a CRM, trigger an internal job, or keep another system in step with TryPost. -They are **outgoing** event subscriptions for the workspace. They are not the [automation Webhook node](/knowledge-base/automations/triggers-and-nodes#output-nodes) (a one-off HTTP call inside a flow), and they are not inbound Telegram/Stripe webhooks. +They are **outgoing** event subscriptions for the workspace — not inbound Telegram/Stripe webhooks. ## Who can manage webhooks @@ -62,7 +62,7 @@ Publish now (dashboard **Post now**, REST `PUT` with `status=publishing`, or `pu Edits that do **not** change status send nothing: content, media, labels, platforms, or a new `scheduled_at` on a post that is already `scheduled`. [Duplicate](/knowledge-base/posts#duplicating-a-post) is a new post, so it fires `post.created`. A failed or published post cannot be republished in place — duplicate it and you will get a fresh lifecycle. -There are no events for comments, mentions, social-account disconnects, or team changes — those stay in [notifications](/knowledge-base/notifications). AI Create has no dedicated `post.ready` event; when the draft is saved you get `post.created` (`created_via` is `web`). Posts created by an [automation](/knowledge-base/automations/introduction) still fire these events (`created_via` is `automation`). Deleting a [workspace](/knowledge-base/workspaces) removes the webhooks with it and does **not** send `post.deleted` for each post. +There are no events for comments, mentions, social-account disconnects, or team changes — those stay in [notifications](/knowledge-base/notifications). AI Create has no dedicated `post.ready` event; when the draft is saved you get `post.created` (`created_via` is `web`). Deleting a [workspace](/knowledge-base/workspaces) removes the webhooks with it and does **not** send `post.deleted` for each post. ## Receive a delivery @@ -151,7 +151,7 @@ For every post event except `post.deleted`, `data` is the post at the moment of | `workspace_id` | Workspace UUID | | `user_id` | Author user UUID | | `status` | `draft`, `scheduled`, `publishing`, `published`, `partially_published`, or `failed` | -| `created_via` | `web`, `api`, `mcp`, `automation`, or `null` | +| `created_via` | `web`, `api`, `mcp`, or `null` | | `content` | Post body. May include HTML from the editor (e.g. `

`), or be an empty string | | `scheduled_at` / `published_at` / `created_at` / `updated_at` | ISO 8601, or `null` — not the `Y-m-d H:i:s` strings used by [`GET /posts`](/api-reference/endpoint/list-posts) | | `author` | `{ id, name }` only — no email — or `null` | @@ -303,9 +303,6 @@ List and update responses omit `signing_secret`. Create, get, and rotate return Five deliveries in a row exhausted their retries. Fix the endpoint, then set status back to **enabled**. - - Workspace webhooks fire on post lifecycle events and are always signed the same way. The [automation Webhook node](/knowledge-base/automations/triggers-and-nodes#output-nodes) is an HTTP step inside a flow — you pick the method, headers, and body template. - Seven days. Older rows are pruned daily. Deleting the webhook removes the remaining logs. @@ -328,12 +325,9 @@ List and update responses omit `signing_secret`. Create, get, and rotate return No. `post.scheduled` only fires when status becomes `scheduled`. Editing `scheduled_at` on an already-scheduled post is silent. - No. Workspace webhooks are always `POST` with `Content-Type`, `User-Agent`, and `X-Webhook-Signature`. For a custom request, use the [automation Webhook node](/knowledge-base/automations/triggers-and-nodes#output-nodes). + No. Workspace webhooks are always `POST` with `Content-Type`, `User-Agent`, and `X-Webhook-Signature`. No. Only the seven post lifecycle events. Comments, mentions, and account disconnects stay in [notifications](/knowledge-base/notifications). - - Yes. Create, schedule, publish, and delete still emit the matching events. `created_via` is `automation`. That is separate from the [automation Webhook node](/knowledge-base/automations/triggers-and-nodes#output-nodes). - diff --git a/self-hosting/configuration.mdx b/self-hosting/configuration.mdx index a86bd08..96eb525 100644 --- a/self-hosting/configuration.mdx +++ b/self-hosting/configuration.mdx @@ -136,7 +136,7 @@ BROADCAST_CONNECTION=reverb | Variable | Recommended | Why | |----------|-------------|-----| -| `QUEUE_CONNECTION` | `redis` | Horizon processes Redis queues (publishing, notifications, automations) | +| `QUEUE_CONNECTION` | `redis` | Horizon processes Redis queues (publishing, notifications, webhooks) | | `CACHE_STORE` | `redis` | Cache + `onOneServer()` schedule locks across instances | | `SESSION_DRIVER` | `database` | Durable sessions behind multiple app workers | | `BROADCAST_CONNECTION` | `reverb` | Real-time dashboard updates | @@ -551,7 +551,7 @@ TRYPOST_USER_AGENT="TryPost.it/1.0 (+https://trypost.it)" | Variable | Default | Description | |----------|---------|-------------| -| `TRYPOST_ALLOW_PRIVATE_NETWORK` | `false` | When `true`, allows HTTP requests from TryPost (RSS, [workspace webhooks](/knowledge-base/webhooks), URL media fetches, etc.) to private/internal network addresses. Keep `false` unless you intentionally need that for a private network install. | +| `TRYPOST_ALLOW_PRIVATE_NETWORK` | `false` | When `true`, allows HTTP requests from TryPost ([workspace webhooks](/knowledge-base/webhooks), URL media fetches, brand autofill, etc.) to private/internal network addresses. Keep `false` unless you intentionally need that for a private network install. | | `TRYPOST_USER_AGENT` | `TryPost.it/1.0 (+https://trypost.it)` | `User-Agent` sent on outgoing HTTP, including webhook deliveries and test pings. | ## Next Steps diff --git a/self-hosting/installation.mdx b/self-hosting/installation.mdx index 9d963e7..69a2001 100644 --- a/self-hosting/installation.mdx +++ b/self-hosting/installation.mdx @@ -69,7 +69,7 @@ FILESYSTEM_DISK=public |-------|-----| | `APP_KEY` | Already set by `key:generate` — encrypts sessions, cookies, encrypted data | | Database | Where posts, users, and Passport clients live. The block above is PostgreSQL; for MySQL use `DB_CONNECTION=mysql` on port `3306` — see [Database](/self-hosting/configuration#database) | -| Redis + queue/cache drivers | Horizon publishes posts and runs automations from Redis queues | +| Redis + queue/cache drivers | Horizon publishes posts and processes background jobs from Redis queues | | `BROADCAST_CONNECTION=reverb` | Live dashboard updates | | `FILESYSTEM_DISK=public` | Local media on disk (use `s3` / `r2` / `spaces` for object storage) | | `SELF_HOSTED=true` | Disables Stripe billing and public `/register` | @@ -175,9 +175,9 @@ This starts `php artisan serve`, a queue listener, log tail, and Vite. Open `htt | Process | Command | Purpose | |---------|---------|---------| | Web (PHP-FPM + Nginx) | see [Production](/self-hosting/production#nginx-configuration) | Serve HTTP | -| **Horizon** | `php artisan horizon` | Queues — publish posts, notifications, automations, webhooks | +| **Horizon** | `php artisan horizon` | Queues — publish posts, notifications, webhooks | | **Reverb** | `php artisan reverb:start` | WebSockets | -| **Scheduler** | cron → `php artisan schedule:run` | Due posts, token refresh, automations | +| **Scheduler** | cron → `php artisan schedule:run` | Due posts, token refresh, stuck-post recovery | Full Supervisor configs, Nginx (including Reverb `/app/` + `/apps/`), SSL, and caches: [Production setup](/self-hosting/production). diff --git a/self-hosting/production.mdx b/self-hosting/production.mdx index dd21615..c9b9fb5 100644 --- a/self-hosting/production.mdx +++ b/self-hosting/production.mdx @@ -61,7 +61,7 @@ TryPost uses queues for critical background processing: - **Sending notifications** (email and in-app) - **Verifying social account connections** - **Processing analytics events** -- **Running automations** +- **Delivering [webhooks](/knowledge-base/webhooks)** and their retries Without a running queue worker, scheduled posts will not be published. Use Supervisor to keep Horizon running. @@ -190,15 +190,11 @@ sudo certbot --nginx -d your-domain.com ## Scheduled Tasks (Cron) -TryPost uses Laravel's task scheduler for several recurring jobs. The scheduler **must** run every minute or scheduled posts won't publish, automations won't fire, expiring tokens won't refresh, and stuck posts won't recover. +TryPost uses Laravel's task scheduler for several recurring jobs. The scheduler **must** run every minute or scheduled posts won't publish, expiring tokens won't refresh, and stuck posts won't recover. | Command | Schedule | Purpose | |---------|----------|---------| | `posts:process-scheduled` | every minute | Dispatches `PublishPost` jobs for posts that are due | -| `automation:fire-schedule` | every minute | Fires time-based automation triggers | -| `automation:process-delays` | every minute | Advances automation runs waiting on delay nodes | -| `automation:recover-stuck-runs` | every 5 minutes | Recovers automation runs stuck mid-flight | -| `automation:prune-dry-runs` | every 10 minutes | Prunes dry-run automation history | | `social:refresh-expiring-tokens` | every 15 minutes | Refreshes OAuth tokens that are about to expire | | `social:recover-stuck-posts` | every 30 minutes | Detects posts stuck in `publishing` and retries or fails them | | `social:check-connections` | daily | Verifies every connected social account still has a valid token | @@ -217,7 +213,7 @@ Add this line: ``` - This is required. Without the cron job, scheduled posts will not be published automatically, automations will stall, and social tokens will expire silently. + This is required. Without the cron job, scheduled posts will not be published automatically and social tokens will expire silently. ## WebSocket Server (Reverb) @@ -275,9 +271,9 @@ Make sure all of these are in place in production: | **Storage link** | `php artisan storage:link` (once, if `FILESYSTEM_DISK=public`) | Local media URLs — skip for S3 / R2 / Spaces | | **Redis** | `QUEUE_CONNECTION=redis` + Redis up | Queues, cache, schedule locks | | **Mail** | SMTP or SendKit | Invites, password reset, alerts | -| **Horizon** | `php artisan horizon` (Supervisor) | Publishes posts, notifications, automations, and [webhooks](/knowledge-base/webhooks) | +| **Horizon** | `php artisan horizon` (Supervisor) | Publishes posts, notifications, and [webhooks](/knowledge-base/webhooks) | | **Reverb** | `php artisan reverb:start` (Supervisor) | Real-time WebSocket updates | -| **Scheduler** | cron → `schedule:run` every minute | Due posts, token refresh, automations | +| **Scheduler** | cron → `schedule:run` every minute | Due posts, token refresh, stuck-post recovery | If Horizon, Reverb, or the scheduler are not running, TryPost will not function correctly. Scheduled posts won't publish, notifications won't send, and the dashboard won't update in real time. diff --git a/self-hosting/upgrading.mdx b/self-hosting/upgrading.mdx index 92dceb6..3f7a052 100644 --- a/self-hosting/upgrading.mdx +++ b/self-hosting/upgrading.mdx @@ -27,7 +27,7 @@ This release adds a database constraint that a workspace cannot hold the same id **Why it matters:** earlier versions could store the same account more than once — the per-network guard was skipped on self-hosted installs, and Pinterest created a fresh row on every connect. Duplicates like that would block the new constraint, so the migration merges them first. -For each duplicated identity it keeps the **most recently created** account, moves that account's scheduled posts and automation targets onto the survivor, and deletes the rest. +For each duplicated identity it keeps the **most recently created** account, moves that account's scheduled posts onto the survivor, and deletes the rest. Merging can leave a post aimed at the same account twice, which would publish it twice. Those repeats are collapsed: