Hilfe

Hier findet ihr Anleitungen, Erklärungen und alles Wichtige rund um Wortfreunde. Damit ihr das Beste aus eurer Content Arbeit herausholen könnt.

Webhooks

Webhooks let you receive real-time HTTP callbacks when events happen in Wortfreunde. Instead of polling the API for changes, your server gets notified automatically.

Setup

Webhooks are configured in Wortfreunde Studio under Settings / Webhooks. You provide a URL, select which events to subscribe to, and receive a signature key for verifying deliveries.

Events

EventDescription
post.updatedA published post's content was updated
post.publishing_pendingA post is ready to publish and awaiting confirmation via the API
post.publishedA post was published
post.unpublishedA published post was reverted to draft

API Platform Events

The post.publishing_pending and post.unpublished events are primarily used with API platform channels. When a post on an API platform channel reaches its scheduled time, Wortfreunde sets it to publishing_pending and fires the post.publishing_pending webhook. Your external system should then:

  1. Receive the webhook and process the post content
  2. Call PATCH /channels/{channel_id}/posts/{id}/publish to confirm publication
  3. Optionally provide external_id and external_url for tracking

See Posts API, API Platform Publishing Workflow for the full flow.

Payload

Every webhook delivery sends a POST request to your URL with a JSON body:

{
  "event": "post.updated",
  "timestamp": "2026-03-09T15:48:46Z",
  "account": {
    "id": 3,
    "name": "Wertstifter GmbH"
  },
  "data": {
    "post": {
      "id": 244,
      "title": "Strukturelle Fokus-Voraussetzungen im Unternehmen",
      "body": "Fokus ist keine Frage der Disziplin. Es ist eine Frage der Struktur...",
      "teaser": null,
      "slug": null,
      "publication_status": "draft",
      "created_at": "2026-03-09T15:48:31.673Z",
      "updated_at": "2026-03-09T15:48:46.870Z",
      "published_at": null,
      "meta_title": null,
      "meta_description": null,
      "tags": [
        { "id": 514, "name": "Positionierung" },
        { "id": 425, "name": "Leadership" },
        { "id": 660, "name": "DeepWork" }
      ],
      "media": [],
      "channel": {
        "id": 17,
        "title": "LinkedIn",
        "platform": "linkedin",
        "team": null,
        "posts_count": 6
      }
    }
  }
}

Top-Level Fields

FieldTypeDescription
eventstringEvent type that triggered this delivery
timestampstringISO 8601 timestamp of when the event occurred
accountobjectThe account that owns the resource
account.idintegerAccount identifier
account.namestringAccount display name
dataobjectEvent-specific payload

Post Object

The data.post object contains the full post at the time of the event. See the Posts API for field descriptions.

Signature Verification

Every webhook delivery is signed with HMAC-SHA256 using your signature key. Verify the following headers to ensure authenticity.

Headers

HeaderDescription
X-Wortfreunde-SignatureHMAC-SHA256 signature of the request body
X-Wortfreunde-TimestampUnix timestamp of signature creation
X-Wortfreunde-EventEvent type that triggered this delivery
X-Wortfreunde-DeliveryUnique delivery identifier

Verification Examples

Python

import hmac
import hashlib

def verify_webhook(payload_body, signature, timestamp, secret):
    """Verify a Wortfreunde webhook signature."""
    message = f"{timestamp}.{payload_body}"
    expected = hmac.new(
        secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

PHP

function verifyWebhook(string $payloadBody, string $signature, string $timestamp, string $secret): bool
{
    $message = $timestamp . '.' . $payloadBody;
    $expected = hash_hmac('sha256', $message, $secret);
    return hash_equals($expected, $signature);
}

Ruby

require 'openssl'

def verify_webhook(payload_body, signature, timestamp, secret)
  message = "#{timestamp}.#{payload_body}"
  expected = OpenSSL::HMAC.hexdigest('SHA256', secret, message)
  Rack::Utils.secure_compare(expected, signature)
end

Verification Steps

  1. Extract X-Wortfreunde-Signature and X-Wortfreunde-Timestamp from the request headers
  2. Concatenate the timestamp and raw request body with a . separator: {timestamp}.{body}
  3. Compute HMAC-SHA256 of the concatenated string using your signature key
  4. Compare the computed signature with the header value using a timing-safe comparison

Responding to Webhooks

Your endpoint should return a 2xx status code within 10 seconds to acknowledge receipt. If the delivery fails, Wortfreunde will retry with exponential backoff.

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours

After 5 failed attempts, the delivery is marked as failed. You can view delivery history and manually retry from Settings / Webhooks in Studio.

Best Practices

  • Respond quickly. Process the payload asynchronously (e.g. queue it) and return 200 immediately. Don't block on database writes or external API calls.
  • Verify signatures. Always validate X-Wortfreunde-Signature before trusting the payload.
  • Handle duplicates. Use X-Wortfreunde-Delivery to deduplicate, the same event may be delivered more than once.
  • Use HTTPS. Your webhook URL should use HTTPS to protect the payload in transit.