> ## Documentation Index
> Fetch the complete documentation index at: https://docs.so-me.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK-Webhooks

> Eingebettete Webhook-Abonnements erstellen und signierte Event-Payloads verifizieren

Eingebettete Webhooks benachrichtigen deinen Server, wenn bei einem beliebigen Endnutzer deines Partnerprojekts etwas passiert. Jede Payload nennt den betroffenen Endnutzer, sodass du sie dem richtigen Kunden zuordnen kannst.

## Ein Abonnement erstellen

Webhook-Endpunkte müssen HTTPS verwenden und öffentlich erreichbar sein.

```ts theme={null}
const webhook = await soMe.webhooks.create({
  url: "https://app.example.com/webhooks/so-me",
  events: ["post.published", "post.failed"],
});

// Save this value immediately; it is returned only on creation.
await secrets.store("some-webhook-secret", webhook.secret!);
```

Lass `events` weg oder übergib ein leeres Array, um jedes erkannte Event zu erhalten, das für deine eingebetteten Endnutzer auftritt.

```ts theme={null}
const subscriptions = await soMe.webhooks.list();
await soMe.webhooks.remove(webhook.id);
```

Nützliche Events für eine eingebettete Veröffentlichungsintegration:

| Event | Bedeutung |
| - | - |
| `social.account_connected` | Ein Social-Konto wurde verbunden |
| `social.account_disconnected` | Ein Social-Konto wurde getrennt |
| `post.scheduled` | Ein Beitrag ist in die Veröffentlichungswarteschlange gelangt |
| `post.published` | Die Social-Plattform hat den Beitrag akzeptiert |
| `post.failed` | Die Veröffentlichung ist fehlgeschlagen |

## Die Signatur verifizieren

Social media studio signiert den exakten rohen HTTP-Request-Body mit HMAC-SHA256. Lies den Body als Text oder Bytes und verifiziere ihn, bevor du das JSON parst.

```ts theme={null}
import {
  verifyWebhookSignature,
  type EmbeddedWebhookEvent,
} from "@social-media-scheduler/sdk";

export async function POST(request: Request) {
  const rawBody = await request.text();
  const signature = request.headers.get("x-webhook-signature") ?? "";

  if (
    !verifyWebhookSignature(
      rawBody,
      signature,
      process.env.SOME_WEBHOOK_SECRET!,
    )
  ) {
    return new Response("Invalid signature", { status: 401 });
  }

  const event = JSON.parse(rawBody) as EmbeddedWebhookEvent;
  await handleEvent(event);
  return new Response(null, { status: 204 });
}
```

Die Signatur kann als hexadezimaler Digest oder mit dem Präfix `v1=` gesendet werden; das SDK akzeptiert beide Formen.

## Aufbau der Payload

```json theme={null}
{
  "id": "delivery_uuid",
  "event": "post.published",
  "createdAt": "2026-08-20T10:00:04.000Z",
  "endUser": {
    "id": "end_user_uuid",
    "externalId": "customer_123"
  },
  "data": {
    "postId": "post_uuid",
    "platform": "THREADS"
  }
}
```

Zustellungsanfragen enthalten außerdem:

| Header | Beschreibung |
| - | - |
| `X-Webhook-Signature` | HMAC-SHA256-Signatur des rohen Bodys |
| `X-Webhook-Event` | Name des Events |
| `X-Webhook-Delivery-Id` | Stabile Zustellungskennung |

## Zustellungsverhalten

* Gib eine `2xx`-Antwort zurück, sobald das Event dauerhaft angenommen wurde.
* Verarbeite Events asynchron, wenn die Arbeit länger als ein paar Sekunden dauern kann.
* Dedupliziere Zustellungen anhand der Payload-`id` oder von `X-Webhook-Delivery-Id`.
* Antworten ohne `2xx`, Netzwerkfehler und Timeouts werden mit exponentiellem Backoff wiederholt.
* Abonnements, die wiederholt fehlschlagen, werden automatisch deaktiviert.

Die Webhook-Zustellung erfolgt mindestens einmal (at least once), daher müssen Handler idempotent sein.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.