A GitHub Action that posts to social media through PostEverywhere. Use it to announce a release on X and LinkedIn, share a new blog post, or send a weekly scheduled post.
One step can post to any account you have connected in PostEverywhere: Instagram, TikTok, YouTube, LinkedIn, Facebook, X, Threads, Pinterest, Bluesky, Telegram and Discord.
- uses: posteverywhere/announce-action@v1
with:
api-key: ${{ secrets.POSTEVERYWHERE_API_KEY }}
platforms: x,linkedinOn a release event, that is all you need. The action posts:
🚀 owner/repo v1.2.0 is out: Release name
https://github.com/owner/repo/releases/tag/v1.2.0
- Connect your social accounts at app.posteverywhere.ai.
- Create an API key at app.posteverywhere.ai/developers. Give it the
readandwritescopes. - In your GitHub repository, go to Settings > Secrets and variables > Actions and add a secret named
POSTEVERYWHERE_API_KEYwith the key. - Add a workflow from the examples below.
name: Announce release
on:
release:
types: [published]
jobs:
announce:
runs-on: ubuntu-latest
steps:
- uses: posteverywhere/announce-action@v1
with:
api-key: ${{ secrets.POSTEVERYWHERE_API_KEY }}
platforms: x,linkedin
content: |
{{repo}} {{release.tag}} is out.
{{release.body}}
{{release.url}}The release body can be long. If X is a target and the text is over 280 characters, X gets a shorter version that keeps the release link. The other platforms get the full text.
name: Share new blog post
on:
push:
branches: [main]
paths: ['blog/**.md']
jobs:
share:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- id: post
run: |
file=$(git diff --name-only --diff-filter=A HEAD~1 HEAD -- 'blog/*.md' | head -n 1)
echo "file=$file" >> "$GITHUB_OUTPUT"
echo "title=$(grep -m1 '^title:' "$file" | sed 's/^title: *//')" >> "$GITHUB_OUTPUT"
echo "slug=$(basename "$file" .md)" >> "$GITHUB_OUTPUT"
- if: steps.post.outputs.file != ''
uses: posteverywhere/announce-action@v1
with:
api-key: ${{ secrets.POSTEVERYWHERE_API_KEY }}
platforms: linkedin,bluesky,threads
content: |
New on the blog: ${{ steps.post.outputs.title }}
https://example.com/blog/${{ steps.post.outputs.slug }}Change the URL and front matter parsing to match your site.
name: Weekly tip
on:
schedule:
- cron: '0 8 * * 1' # every Monday 08:00 UTC
jobs:
tip:
runs-on: ubuntu-latest
steps:
- uses: posteverywhere/announce-action@v1
with:
api-key: ${{ secrets.POSTEVERYWHERE_API_KEY }}
account-ids: 2280,2291
content: 'Tip of the week: pin your best post to the top of your profile.'
media-url: https://example.com/images/weekly-tip.pngGitHub may start cron workflows a few minutes late. To publish at an exact time, set schedule and PostEverywhere will publish then:
schedule: 2026-10-05T09:00
timezone: Europe/LondonSet draft: true to save the post as a draft. You can then review and publish it in PostEverywhere.
| Input | Required | Default | Description |
|---|---|---|---|
api-key |
yes | PostEverywhere API key. Pass it from a secret. | |
content |
no | Post text. Supports the placeholders below. Required unless the event is release. |
|
account-ids |
no | Comma-separated account IDs (integers). | |
platforms |
no | Comma-separated platforms, for example x,linkedin. Posts to every connected account on each platform. twitter also works for X. |
|
schedule |
no | ISO 8601 time to publish. Leave empty to publish now. | |
timezone |
no | UTC |
IANA timezone, for example Europe/London. A schedule without an offset is read in this timezone. |
draft |
no | false |
Save as a draft instead of publishing. |
media-url |
no | Public URL of one image (JPEG, PNG, GIF, WebP, HEIC, up to 25 MB) or MP4 video to attach. | |
fail-on-error |
no | true |
Fail the step if the post cannot be created. Set to false to log a warning instead. |
Set account-ids, platforms, or both. The action posts to the combined list. With platforms, it skips accounts that need to be reconnected and logs a warning.
| Placeholder | Value |
|---|---|
{{repo}} |
owner/repo |
{{release.tag}} |
Release tag, for example v1.2.0. On a tag push, the tag name. |
{{release.name}} |
Release title, or the tag when the title is empty. |
{{release.url}} |
Link to the release page. |
{{release.body}} |
Release notes, cut to 500 characters at a word boundary. HTML comments are removed. |
You can also use GitHub expressions such as ${{ github.event.head_commit.message }} in content.
| Output | Description |
|---|---|
post-id |
ID of the created post. |
status |
Post status from PostEverywhere, for example publishing, scheduled or draft. error if the step failed. |
Use the post ID with the PostEverywhere API or CLI to check results later.
- The step finishes when PostEverywhere accepts the post. Publishing to each platform happens after that. Check the result in PostEverywhere, or subscribe to webhooks.
- Each platform has its own rules. PostEverywhere checks the post and returns a clear error if a platform cannot accept it, for example a video to a platform that needs an image.
- The action masks the API key in logs.
- If the API returns a rate limit error, the action waits and tries again. It never sends the same post twice after a server error.
npm install
npm test # unit tests, no network
npm run build # bundles src/ into dist/index.jsCommit dist/ with every change to src/.