Lists the articles Postedin has ready to publish for a project, and creates the selected one as a WordPress draft with its images pulled into the media library.
This replaces the old XML-RPC integration, in which the Postedin app pushed posts into WordPress using a stored administrator password. Here the direction is reversed: WordPress pulls, authenticated with a per-project API key, so Postedin never holds a WordPress credential.
WordPress Postedin app
───────── ────────────
Settings → Postedin
Test connection ──────────────▶ GET /iapi/v1/ping
──────────────▶ POST /iapi/v1/wordpress/pair
creates the publisher for this site
Postedin → Ready to publish
──────────────▶ GET /iapi/v1/articles
Create draft
──────────────▶ GET /iapi/v1/articles/{id}
sideload images
rewrite image URLs in the body
wp_insert_post (draft)
──────────────▶ POST /iapi/v1/articles/{id}/publications
marks the article published,
writes the comment + audit log
redirect to the editor
Creating the draft marks the article as published in Postedin straight away — the same thing the old "Send draft" button did.
Send whoever runs the site two things: the plugin zip and an API key.
Getting the zip. Either download it from the
latest release,
or build it yourself with bin/build (produces
dist/postedin-integration-<version>.zip).
Getting a key. In Postedin, open the project → Settings → Integrations → create an API key. One key per site. A key only grants read access to that one project's articles, plus the ability to report back which post was created, and can be revoked at any time.
What they do:
- Plugins → Add New → Upload Plugin → choose the zip → Install Now → Activate.
- Settings → Postedin. Enter the Postedin URL (
https://app.postedin.comis prefilled) and paste the API key. Save. - Press Test connection. It should name the project. This also registers the site with Postedin so drafts can be reported back.
- Postedin → Ready to publish.
They need WordPress 6.0+, PHP 8.1+, and a user who can publish_posts to use the
screen (manage_options for the settings page).
The plugin sets Update URI: false, so WordPress will never offer an update for
it from wordpress.org — important, since a slug collision there could otherwise
push a stranger's code onto a client site. The trade-off is that there is no
automatic update channel: a new version means sending a new zip and re-uploading
it over the old one, which WordPress handles without losing settings.
WordPress 6.0+, PHP 8.1+. The plugin refuses to boot and shows an admin notice rather than fataling if either is older.
No runtime dependencies — src/autoload.php is a hand-rolled PSR-4 loader, so
there is no vendor/ to ship. Composer is dev-only.
bin/start # WordPress on http://localhost:8092 (admin / password)
bin/stop # stop, keeping the database
bin/stop --clean # stop and wipe the volumes
bin/wp plugin list # wp-cli inside the container
bin/build # dist/postedin-integration-<version>.zipThe plugin directory is bind-mounted into the container, so edits are live.
See CONTRIBUTING.md for conventions and the release process.
bin/start points the plugin at http://host.docker.internal:8081, which is
where the Postedin app serves in local development (APP_PORT=8081 in its
.env). Override with POSTEDIN_APP_URL=... bin/start.
Ports used: 8092 WordPress, 33061 MariaDB. Override with WP_PORT and
DB_PORT.
PairController prefixes publisher names with DEVTEST: outside production,
which is what lets the app record publications from a non-production
environment — see assertEnvironmentAllowsSending() in
app/PublisherPublication.php. No extra setup is needed.
| Key | Meaning |
|---|---|
_postedin_revision_id |
The Postedin article revision this post came from |
_postedin_content_request_id |
Its content request |
_postedin_publisher_id |
The Postedin publisher representing this site |
_postedin_imported_at |
UTC timestamp of the import |
_postedin_sync_pending |
Present when Postedin could not be told about the draft; the error message |
Attachments carry _postedin_ref, so importing the same image twice reuses the
existing attachment instead of duplicating it.
If the report-back to Postedin fails, the draft is kept and flagged with
_postedin_sync_pending, and a notice offers a retry. The app's endpoint is
idempotent for a given post ID, so retrying will not double-post the comment or
audit-log entry.
PSR-12 via Laravel Pint (composer lint, composer lint-fix), matching the
rest of the Postedin codebase rather than WordPress Coding Standards.
GPL-2.0-or-later — see LICENSE. The plugin calls WordPress APIs, so it inherits WordPress's licence.