Post with PHP

Post to social media
with PHP.

PHP talks to PostLake with ordinary HTTPS. Same request body as the docs quickstart, profile name, text, optional filters.

Get started free →

Free tier. No card · one API for every network · full MCP access

In shortOne cURL (or Guzzle) POST to /v1/posts from PHP. Address a profile; decode targets[] before you trust the result.

When this guide is for you

Your product or CMS is PHP and you want fan-out without Facebook/Twitter SDKs.

Before you start

Same setup the docs quickstart uses. Do this once:

  1. Sign up at app.postlake.dev and verify your email (unlocks free credits).
  2. On Channels, create a profile (e.g. my-brand) and connect at least one account. Bluesky is the fastest first channel: no app review. Instagram/TikTok/Facebook need each platform's review before API posting.
  3. Account menu → API Keys → create a key (sk_live_…). It shows once; treat it like a password.

Working example in PHP

Connect accounts once in the dashboard, then this is the publish call:

<?php
$payload = json_encode([
    "text" => "Hello from PHP 👋",
    "profile" => "my-brand",
]);
$ch = curl_init("https://api.postlake.dev/v1/posts");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("POSTLAKE_API_KEY"),
        "Content-Type: application/json",
        "Idempotency-Key: hello-php-001",
    ],
    CURLOPT_POSTFIELDS => $payload,
]);
$raw = curl_exec($ch);
$post = json_decode($raw, true);
foreach ($post["targets"] as $t) {
    echo $t["platform"] . " " . $t["state"] . PHP_EOL;
}

Make it work in PHP

Tool-specific glue on top of the shared setup above:

  1. Load the API key from the environment (not from source control).
  2. POST JSON with profile set to your Channels profile name.
  3. json_decode the body and loop targets: don't stop at HTTP 200.
  4. Reuse the same pattern for schedule (scheduledAt) and media (med_… ids).

Read the response (don't skip this)

You get one Post with an overall state and a targets[] array. One entry per account. Always check each target; partial success is normal.

{
  "id": "post_a1b2c3",
  "state": "partial",
  "targets": [
    { "platform": "bluesky",  "state": "published", "url": "https://bsky.app/…" },
    { "platform": "linkedin", "state": "failed",
      "error": { "type": "invalid_request", "message": "…", "retryable": false } }
  ]
}

Where the post goes

Same rules as the docs. Pick one addressing style:

See Publishing: where to post.

Do more (same API)

Pitfalls specific to this path

Prefer an assistant over PHP code? Point it at MCP (https://api.postlake.dev/mcp). Prefer the dashboard? Use Quickstart → No code.

Common questions

How do I post to social media with PHP?

cURL or Guzzle POST to https://api.postlake.dev/v1/posts with Bearer auth and JSON { text, profile }. Decode targets[] for per-network results.

Do I need a package per network?

No. One HTTP call to PostLake covers every connected account on the profile.

Can I schedule from PHP?

Yes, add scheduledAt as UTC or a naive local time plus timezone. See docs → Scheduling for edit/cancel endpoints.

Go deeper in the docs

These guides stay short on purpose. Canonical behaviour lives here:

Also: Media · Errors · MCP · Analytics

Related guides

All guides · Full docs · llms.txt · Markdown

Stuck? The docs are the source of truth, start at Publishing.

Open the dashboard →