Webhooks

Erhalten Sie eine signierte Benachrichtigung, wenn eine Generierung der Direct API abgeschlossen ist, prüfen Sie sie und lesen Sie die Generierung für die Details.

Ein Webhook ist ein HTTPS-Endpunkt von Ihnen, den Morphic aufruft, wenn eine Generierung einen endgültigen Status erreicht. Zustellungen werden signiert, etwa einen Tag lang wiederholt und protokolliert. Jedes Ereignis ist eine schlanke Benachrichtigung: Es sagt, welche Generierung wie abgeschlossen wurde, und Sie lesen die Generierung mit Ihrem Schlüssel, um ihre Assets, ihre Abrechnung und ihre Fehlermeldung zu erhalten.

Einen Endpunkt registrieren

POST /v1/direct/webhooks benötigt die Berechtigung generations:write.

curl -s https://mcp.morphic.com/v1/direct/webhooks \
  -H "Authorization: Bearer $MORPHIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "url": "https://hooks.example.com/morphic",
        "events": ["generation.succeeded", "generation.failed", "generation.cancelled"],
        "description": "Production order pipeline"
      }'
FeldRegeln
urlHTTPS auf einem öffentlichen Host (keine IP-Literale, keine privaten oder lokalen Adressen), bis zu 2048 Zeichen
eventsein oder mehrere Ereignistypen
descriptionoptional, bis zu 200 Zeichen

Die Antwort ist 201:

{
  "webhook": {
    "id": "01929a10-0c3d-7f44-8a21-0b1c2d3e4f50",
    "url": "https://hooks.example.com/morphic",
    "events": ["generation.succeeded", "generation.failed", "generation.cancelled"],
    "description": "Production order pipeline",
    "created_at": "2026-10-25T08:00:00.000Z",
    "signing_secret": "whsec_4b1e…"
  }
}
  • signing_secret wird nur in dieser Antwort angezeigt. Bewahren Sie es so sicher auf wie den API-Schlüssel.
  • Um das Secret zu rotieren, registrieren Sie einen neuen Endpunkt, stellen Ihre Aufrufe auf dessen ID um und löschen dann den alten.
  • Eine Organisation kann bis zu 10 Endpunkte haben.

Endpunkte verwalten

AnfrageBerechtigungFunktion
GET /v1/direct/webhooksassets:readlistet Endpunkte als { "webhooks": [ … ] } auf, nie mit ihren Secrets
DELETE /v1/direct/webhooks/{webhook_id}generations:writeentfernt den Endpunkt; noch ausstehende Zustellungen an ihn werden verworfen

Einen Endpunkt an einen Aufruf anhängen

Übergeben Sie webhook_id im Body des Tool-Aufrufs. Jede Generierung, die dieser Aufruf startet, wird an diesen Endpunkt zugestellt, sobald sie einen endgültigen Status erreicht, den der Endpunkt abonniert hat. Aufrufe ohne webhook_id senden keine Webhooks.

Die Tools, die Videos auf den Servern von Morphic rendern (video_compose, die video_*-Transformationen und burn_subtitles), akzeptieren webhook_id noch nicht; fragen Sie ihre Generierungen per Polling ab.

Ereignistypen

EreignisGesendet, wenn
generation.succeededdie Generierung mit einer Ausgabe abgeschlossen wurde
generation.faileddie Generierung fehlgeschlagen ist; ihre Belastung wird erstattet
generation.cancelleddie Generierung abgebrochen wurde; ihre Belastung wird erstattet
  • Jede Generierung erzeugt höchstens ein Ereignis.
  • queued und in_progress werden nicht zugestellt; fragen Sie sie per Polling ab, wenn Sie sie benötigen.
  • Eine Generierung wird ab ihrem Start 72 Stunden lang beobachtet. Eine, die später endet, sendet kein Ereignis, lesen Sie sie also stattdessen.

Die Zustellung

POST /morphic HTTP/1.1
Host: hooks.example.com
Content-Type: application/json
User-Agent: Morphic-Webhooks/1.0
Morphic-Event-Id: 0192a7c0-5d4e-7b3a-8c2d-1e0f9a8b7c6d
Morphic-Delivery-Id: 0192a7c0-6e5f-7c4b-9d3e-2f1a0b9c8d7e
Morphic-Event-Type: generation.succeeded
Morphic-Signature: t=1792919741,v1=5f8a0c…e21b

{
  "id": "0192a7c0-5d4e-7b3a-8c2d-1e0f9a8b7c6d",
  "type": "generation.succeeded",
  "created_at": "2026-10-25T09:15:42.410Z",
  "api_version": "v1",
  "data": {
    "generation": {
      "object": "generation",
      "id": "0192a7b3-a1c4-7e02-8f9d-1a2b3c4d5e6f",
      "tool": "generate_video",
      "status": "succeeded",
      "completed_at": "2026-10-25T09:15:41.902Z",
      "error_code": null,
      "metadata": { "order_id": "4411" }
    }
  }
}

data.generation enthält nur diese Felder:

FeldBedeutung
object, id, tool, status, completed_at, metadatawie im Generierungsobjekt
error_codenull oder der Code einer failed-Generierung

Ein Ereignis enthält nie Ausgaben, Links, Abrechnung, das Modell oder die Fehlermeldung, sodass eine Zustellung, die am falschen Ort oder in einem Log landet, nichts preisgibt. Lesen Sie die Generierung nach dem Empfang mit Ihrem Schlüssel: GET /v1/direct/generations/{id} oder für mehrere das gebündelte Lesen. Wenn ein Ereignis gesendet wird, steht an seiner Abrechnung nichts mehr aus, dieses Lesen ist also endgültig.

HeaderBedeutung
Morphic-Event-Iddie ID des Ereignisses, bei jeder Wiederholung identisch; deduplizieren Sie anhand dieser ID
Morphic-Delivery-Iddieser eine Zustellversuch; bei jeder Wiederholung anders
Morphic-Event-Typeder type des Bodys
Morphic-Signaturet=<unix seconds>,v1=<hex HMAC-SHA256>

Ein Ereignis wird in der Regel innerhalb von etwa einer Minute gesendet, nachdem die Generierung ihren endgültigen Status erreicht hat. Es ist kein Echtzeit-Stream: Für die geringste Latenz bei einer Generierung, auf die Sie gerade warten, fragen Sie sie per Long-Polling ab.

Die Signatur prüfen

v1 ist der hexadezimale HMAC-SHA256, mit dem signing_secret Ihres Endpunkts als Schlüssel, über den String {t}.{raw request body}.

  1. Teilen Sie den Header an , in t und v1 auf.
  2. Berechnen Sie HMAC_SHA256(secret, t + "." + raw_body) über die empfangenen Rohbytes, vor jedem JSON-Parsing oder jeder erneuten Serialisierung.
  3. Vergleichen Sie das Ergebnis in konstanter Zeit mit v1.
  4. Weisen Sie die Zustellung zurück, wenn t mehr als 5 Minuten von der aktuellen Zeit abweicht, um Replay-Angriffe zu verhindern.
import crypto from 'node:crypto';
import express from 'express';

const app = express();

app.post('/morphic', express.raw({ type: 'application/json' }), (req, res) => {
  const header = req.get('Morphic-Signature') ?? '';
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const expected = crypto
    .createHmac('sha256', process.env.MORPHIC_WEBHOOK_SECRET)
    .update(`${parts.t}.${req.body}`)
    .digest('hex');

  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= 300;
  const valid =
    parts.v1?.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));

  if (!fresh || !valid) return res.sendStatus(400);

  const event = JSON.parse(req.body);
  enqueue(event); // process asynchronously, keyed by event.id
  res.sendStatus(204);
});

Ein ungeprüfter Endpunkt ist eine offene Tür: Jeder, der seine URL kennt, kann Ihnen melden, dass eine Generierung abgeschlossen ist. Prüfen Sie jede Signatur und weisen Sie einen Zeitstempel zurück, der älter als 5 Minuten ist.

Antworten und Wiederholungen

  • Antworten Sie innerhalb von 10 Sekunden mit einem beliebigen 2xx und erledigen Sie die Arbeit danach.
  • Alles andere ist ein fehlgeschlagener Versuch: ein Status außer 2xx, ein Timeout, eine abgelehnte Verbindung, ein TLS-Fehler.
  • Weiterleitungen werden nicht verfolgt; ein 3xx ist ein fehlgeschlagener Versuch.
  • Die Reihenfolge ist nicht garantiert, und ein Ereignis kann mehrfach ankommen. Machen Sie Ihren Handler idempotent bezüglich Morphic-Event-Id oder data.generation.id, da eine Generierung höchstens ein Ereignis hat.

Ein fehlgeschlagener Versuch wird wiederholt nach:

Wiederholung1234567
Wartezeit nach dem vorherigen Versuch1 min5 min15 min1 h3 h6 h12 h

Nach der 7. Wiederholung, etwa 22 Stunden nach dem ersten Versuch, wird das Ereignis verworfen. Die Generierung selbst ist davon nicht betroffen: Lesen Sie sie mit GET /v1/direct/generations/{id}.

Zustellprotokoll

GET /v1/direct/webhooks/{webhook_id}/events (Berechtigung assets:read) liefert die letzten 20 Ereignisse des Endpunkts, jeweils mit dem exakt gesendeten Body und dem Ergebnis jedes Versuchs. Hängen Sie ?generation_id=… an, um die Ereignisse einer einzelnen Generierung zu erhalten.

{
  "webhook_events": [
    {
      "id": "0192a7c0-5d4e-…",
      "type": "generation.succeeded",
      "generation_id": "0192a7b3-…",
      "status": "delivered",
      "created_at": "2026-10-25T09:15:42.410Z",
      "payload": { "…": "the body that was sent" },
      "attempts": [
        { "id": "0192a7c0-6e5f-…", "attempted_at": "2026-10-25T09:15:42.900Z", "response_status": 204, "duration_ms": 131, "error": null, "response_body_excerpt": null }
      ]
    }
  ]
}
Ereignis-statusBedeutung
pendingnoch nicht zugestellt; weitere Versuche können folgen
deliveredIhr Endpunkt hat mit 2xx geantwortet
abandoneddie letzte Wiederholung ist fehlgeschlagen, oder der Endpunkt wurde entfernt
skippedder Endpunkt hat diesen Ereignistyp nicht abonniert

Webhooks sind das günstigere und schnellere Signal, keine Garantie. Fragen Sie Generierungen, von denen Sie nichts gehört haben, gelegentlich als Sicherheitsnetz ab.


Wenn Sie Probleme haben oder Fragen haben, können Sie sich gerne an uns wenden. Wir helfen Ihnen gerne. Schreiben Sie uns an support@morphic.com.

Auf dieser Seite