FoPost LogoFoPost Docs
Events

Webhooks

Receive server-side notifications for publishing events.

Webhooks

Webhooks allow OwlStack to notify your application when events happen on the server - such as scheduled posts being published, batch operations completing, or retries succeeding.

Setup

  1. Go to the OwlStack dashboard
  2. Navigate to Project Settings > Webhooks
  3. Click Add Webhook Endpoint
  4. Enter your endpoint URL (e.g., https://example.com/webhooks/owlstack)
  5. Select which events to receive
  6. Copy the signing secret

Events

EventDescriptionPlan
post.publishedA post was successfully publishedAll
post.failedA post failed to publishAll
batch.completedA batch publish operation completedPro
schedule.firedA scheduled post was publishedPro
schedule.failedA scheduled post failedPro

Payload format

{
  "event": "post.published",
  "timestamp": "2026-02-14T10:30:00Z",
  "data": {
    "post_id": "ps_abc123",
    "platform": "twitter",
    "external_id": "1234567890",
    "external_url": "https://twitter.com/user/status/1234567890"
  }
}

Verifying webhooks

Every webhook request includes an X-OwlStack-Signature header. Verify it using the signing secret:

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_OWLSTACK_SIGNATURE'];
$secret = env('OWLSTACK_WEBHOOK_SECRET');

$expected = hash_hmac('sha256', $payload, $secret);

if (! hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

Laravel example

Route::post('/webhooks/owlstack', function (Request $request) {
    $event = $request->input('event');
    $data = $request->input('data');

    match ($event) {
        'post.published' => Log::info("Published to {$data['platform']}"),
        'post.failed' => Log::error("Failed on {$data['platform']}"),
        'batch.completed' => Log::info("Batch completed"),
        default => null,
    };

    return response('OK', 200);
});

Retry policy

If your endpoint returns a non-2xx status code, OwlStack retries the webhook up to 3 times with exponential backoff (1 minute, 5 minutes, 30 minutes).

On this page