Zum Hauptinhalt springen

Beitragslisten

Eine Beitragsliste ist der dritte Weg, auf dem Daten ankommen: Jemand schreibt sie, statt dass ein Feed sie einspielt. Die Liste ist ein Name; die Beiträge darauf wählen jeweils ihre eigene Vorlage, enthalten den in die Eingaben dieser Vorlage getippten Inhalt und sagen, wann sie hinausgehen. In diesem Moment wird ein Beitrag zu einem Ereignis wie jedes andere und nimmt denselben Weg, auf jedem Kanal, der die Liste empfängt.

Die API nennt diese Queues, und ein Beitrag darauf ist ein Package. Im Dashboard finden sie sich im Beitragseditor, in dessen Karte Manuelle Beitragslisten, wo die Wörter Beitragsliste und Beitrag lauten; der Berechtigungsbereich ist Beitragseditor (postlists).

MethodePfadBerechtigung
GET/v1/queuespostlists:read
POST/v1/queuespostlists:write
PATCH/v1/queues/{id}postlists:write
POST/v1/queues/{id}/deletepostlists:write
POST/v1/queues/{id}/packagespostlists:write
PATCH/v1/queues/{id}/packages/{packageId}postlists:write
POST/v1/queues/{id}/packages/{packageId}/deletepostlists:write

Eine Liste erstellen​

Eine Liste ist ein Name und sonst nichts. Ihre Beiträge werden einzeln hinzugefügt.

curl http://localhost:4000/v1/queues \
-H "Authorization: Bearer rw_your_key_here" \
-H "Content-Type: application/json" \
-d '{"name":"Docs examples list"}'
{
"queue": {
"id": "01M2SQRG1HVVSB4P1D04WT0T8Z",
"name": "Docs examples list",
"enabled": true,
"posts": [],
"subscribers": 0,
"listeners": [],
"brands": []
}
}

201. name hat 1 bis 80 Zeichen und muss im Workspace frei sein; eine Wiederholung ist ein 409. PATCH /v1/queues/{id} nimmt name und enabled und antwortet mit der Liste als queue.

Eine ausgeschaltete Liste (enabled: false) hält nichts zurück: Ein Beitrag, der fällig wird, während sie aus ist, geht trotzdem los, erreicht keinen Kanal und wird später nicht erneut gesendet. Schalten Sie sie aus, um eine Liste zu stoppen, nicht um sie zu pausieren; um einen Beitrag anzuhalten, ändern Sie seine Zeit.

Ein Workspace hält bis zu 50 Listen und 5.000 Beiträge über alle zusammen, sofern Reelwire es nicht anders gesetzt hat; darüber nennt ein 409 die Zahl. Beiträge, die schon hinausgegangen sind, zählen mit, bis sie gelöscht werden.

Einen Beitrag planen​

curl http://localhost:4000/v1/queues/01M2SQRG1HVVSB4P1D04WT0T8Z/packages \
-H "Authorization: Bearer rw_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"title": "Weekly market wrap",
"templateId": "tpl_39bc5fecfa42",
"templateVariant": "Corporate glass",
"scheduledFor": "2026-09-25T08:00:00Z",
"data": {
"clipData": {
"title": "Weekly market wrap",
"items": [
{ "text": "Bund yields up", "detail": "The ten-year closed at 2.41 per cent" },
{ "text": "Euro steady" },
{ "text": "Oil lower" }
],
"source": "Orchid Invest"
},
"metaData": {
"title": "Weekly market wrap",
"captionShort": "Three things that moved the week.",
"hashtags": ["markets"]
}
}
}'
{
"package": {
"id": "01M2SQRR3PB0MQ2M2GP9A0ZT82",
"title": "Weekly market wrap",
"templateId": "tpl_39bc5fecfa42",
"templateVariant": "Corporate glass",
"templateVersion": null,
"data": {
"clipData": {
"items": [
{ "text": "Bund yields up", "detail": "The ten-year closed at 2.41 per cent" },
{ "text": "Euro steady" },
{ "text": "Oil lower" }
],
"title": "Weekly market wrap",
"source": "Orchid Invest"
},
"metaData": {
"title": "Weekly market wrap",
"hashtags": ["markets"],
"captionShort": "Three things that moved the week."
}
},
"locales": null,
"scheduledFor": "2026-09-25T08:00:00.000Z",
"state": "SCHEDULED",
"firedAt": null,
"ingestEventId": null,
"error": null,
"waitingForPicturesSince": null,
"waitingFor": [],
"outcome": null
}
}

Der Text:

FeldErforderlichWas es ist
titleja1 bis 120 Zeichen. Der Name des Beitrags in der Liste, nicht der eigene Titel des Beitrags, der metaData.title ist.
templateIdjaDie Vorlage, mit der dieser Beitrag gerendert wird, eine, die diesem Workspace angeboten wird. Jede andere ist ein 404.
templateVariantneinWelcher Zuschnitt, nach seinem Namen, etwa Corporate glass. Fehlt er, ist es der erste der Vorlage. Ein Zuschnitt, den die Vorlage nicht hat, ist ein 400, der die nennt, die sie hat.
templateVersionneinEine exakte major.minor.patch oder "latest". Fehlend und "latest" speichern beide null, was dem neuesten Build folgt, wenn der Beitrag losgeht. Eine Version, die es nicht gibt, ist ein 400. Vorläufig steht jede Vorlage auf 1.0.0.
scheduledForjaEin ISO-Zeitpunkt oder die Zeichenfolge "now".
datajaDer Inhalt, in der eigenen Eingabeform der Vorlage.

201. Hier gibt es keine Feldzuordnung. Ein Beitrag wird direkt in die Eingaben der Vorlage geschrieben, es gibt also nichts, woraus zugeordnet werden könnte: Fragen Sie GET /v1/formats/template/{templateId}, was sie sind, mit ?variant= für eine Vorlage, deren Varianten jeweils ihren eigenen Inhalt nehmen. Das Beispiel ist Liste, deren Clip aus einem title und bis zu zwölf items besteht, jedes ein text mit optionalem detail. Ein Bild in data ist eine Datei aus der Mediathek, { "url": "media://...", "alt": "..." }; eine Webadresse wird abgelehnt. Was in clipData und metaData steht, finden Sie unter Ereignisse senden.

Sprachkopien reisen innerhalb von data, unter einem Block locales, den die Vorlage prüft, nicht in einem Feld locales der Anfrage. Die Antwort zeigt immer locales: null; diese Spalte wird aus einer Anfrage nicht mehr geschrieben.

Der Inhalt wird beim Speichern geprüft, nicht beim Losgehen​

Derselbe Validator, der einen Stream schützt, prüft, was Sie senden, gegen den Build, mit dem der Beitrag tatsächlich gerendert würde, in dem Moment, in dem Sie speichern. Ein Beitrag, der gespeichert wird, ist ein Beitrag, der gerendert wird.

curl http://localhost:4000/v1/queues/01M2SQRG1HVVSB4P1D04WT0T8Z/packages \
-H "Authorization: Bearer rw_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"title": "Missing its points",
"templateId": "tpl_39bc5fecfa42",
"scheduledFor": "now",
"data": { "clipData": { "title": "Missing its points" } }
}'
{
"error": {
"type": "https://reelwire.io/errors/schema_validation",
"code": "schema_validation",
"message": "The post does not fit the template",
"requestId": "01M2SQS36D5F7W5S7WSZPHMADF",
"details": [{ "path": "/clipData", "message": "missing items" }]
}
}

Der Fehlschlag landet bei der Person, die ihn beheben kann, statt in einem Worker um sechs Uhr an einem Sonntag. Jedes Detail nennt ein Feld und was damit nicht stimmt: fehlend, keines, das diese Vorlage nimmt, über seinem Limit oder keiner der Werte, die es akzeptiert. Geprüft wird gegen die eigene Variante des Beitrags, da die Varianten einer Branchenvorlage (Finance, Influencer, Retail, Tech, Public bodies) jeweils ihren eigenen Inhalt nehmen. Die Prüfung sieht auf die Form eines Bildes, nicht auf die Mediathek: Eine media://-Referenz auf eine Datei, die die Mediathek nicht hält, wird gespeichert und als fehlendes Bild gerendert. POST /v1/templates/{templateId}/validate nennt auch diese, bevor Sie speichern.

Eine Zeit in der Vergangenheit wird abgelehnt​

Eine Zeit, die mehr als eine Minute zurückliegt, ist ein Fehler und keine Anweisung:

{
"error": {
"type": "https://reelwire.io/errors/schema_validation",
"code": "schema_validation",
"message": "That time has already passed. Pick Right away, or a time to come.",
"requestId": "01M2SQS34CCN1K6S6MZXKD631Y",
"details": []
}
}

Senden Sie "scheduledFor": "now", wo Sie sofort meinen.

Eine Liste zurücklesen​

curl http://localhost:4000/v1/queues \
-H "Authorization: Bearer rw_your_key_here"
{
"queues": [
{
"id": "01M2985NYG2GJ450CQAF3DP5YK",
"name": "Enterprise 2 Post list 1",
"enabled": true,
"posts": [],
"subscribers": 3,
"listeners": [
{ "channelId": "01M1VFRWE7EWSY5D7QDQ0KNK1S", "channelName": "Channel 1 en", "locale": "en", "brandId": "01M1VFRWDZ6KBJ1T4Q3V5N8X2C", "brandName": "Brand 1" },
{ "channelId": "01M2985NXBN97TVSF6AN19TDN2", "channelName": "Channel 7 en", "locale": "en", "brandId": "01M1VFRWDZ6KBJ1T4Q3V5N8X2C", "brandName": "Brand 1" },
{ "channelId": "01M2985NXSH4KRQHCP6WJ2KMFR", "channelName": "Channel 13 en", "locale": "en", "brandId": "01M1VFRWDZ6KBJ1T4Q3V5N8X2C", "brandName": "Brand 1" }
],
"brands": [
{
"id": "01M1VFRWDZ6KBJ1T4Q3V5N8X2C",
"name": "Brand 1",
"text": {
"description": "Trading involves risk.",
"link": { "label": "Read more", "url": "https://example.com/more" },
"hashtags": ["markets"]
},
"locales": { "de": { "description": "Handel birgt Risiken.", "hashtags": ["maerkte"] } }
}
]
}
]
}

Listen kommen in der Reihenfolge der Namen, und die Beiträge in jeder (posts, in der obigen Form) nach der Zeit, zu der sie hinausgehen. listeners ist jeder Kanal, der die Liste empfängt, mit seiner Sprache (locale) und seiner Marke: Diese Sprachen sind die, für die sich lohnt, die locales eines Beitrags zu schreiben, da jeder Kanal die Kopie seiner eigenen Sprache über dem Standard rendert. brands ist jede Marke der empfangenden Kanäle einmal, mit dem, was sie nach dem eigenen Text jedes Beitrags hinzufügt (text: ihre description, link und hashtags), und dasselbe in jeder Sprache, in der die Marke ihren eigenen Beitragstext geschrieben hat (locales, nach Sprachcode).

Der state eines Beitrags ist SCHEDULED bis zu seiner Zeit, dann FIRED; CANCELLED, sobald er abgebrochen wurde, und FAILED, mit dem Grund in error, wenn er gar nicht losgehen konnte, etwa weil eine Vorlage keinen Build zum Rendern mehr hat.

Ein Beitrag, dessen Inhalt ein Bild (media://) nennt, das die Mediathek nicht hält, geht nie ohne es los: Wenn seine Zeit kommt, bleibt er SCHEDULED, waitingForPicturesSince sagt, seit wann, waitingFor listet die Dateinamen, und er geht los, sobald jede in der Mediathek ist, etwa einmal pro Minute geprüft. Beide sind null und [] bei einem Beitrag, der nicht wartet. Ein Beitrag darf geschrieben werden, der ein Bild nennt, das erst noch kommt, sodass ein Plan gemacht werden kann, bevor die Fotos aufgenommen sind; wer veröffentlicht, erhält einige Tage vor der Fälligkeit eine E-Mail, solange ein Bild fehlt. Eine Änderung seiner data oder scheduledFor beginnt von vorn.

Jeder Beitrag trägt ein outcome, sobald er losgegangen ist, gezählt über die Kanäle, die er erreicht hat: channels, rendering, rendered, renderFailed, published, handedOver (per E-Mail oder Webhook übergeben, und noch niemand hat ihn als veröffentlicht gemeldet), emailed (dieselbe Zahl, unter dem Namen, den sie hatte, als E-Mail der einzige Weg war), awaitingApproval und publishFailed.

outcome ist null bei einem Beitrag, der noch losgeht. Ein Beitrag geht los, ob jemand empfängt oder nicht, sodass „gesendet“ allein nicht sagen kann, ob ein Video erstellt wurde: Dies kann es.

Ändern und Abbrechen​

PATCH /v1/queues/{id}/packages/{packageId} akzeptiert title, scheduledFor, templateId, templateVariant, templateVersion, data und state, wobei state "CANCELLED" ist (jeder andere Zustand ist ein 400). Es antwortet mit dem Beitrag als package. Eine neue Vorlage, ein neuer Zuschnitt, Build oder Inhalt wird als Ganzes erneut geprüft, weil Inhalt, der zur alten Vorlage passte, zur neuen vielleicht nicht passt.

Zwei Dinge sind zu wissen. Nur ein Beitrag, der noch SCHEDULED ist, kann geändert werden; ein Beitrag, der hinausgegangen ist, ist ein Nachweis von etwas, das geschehen ist, und ihn zu bearbeiten würde die Geschichte umschreiben. Und das Ändern der Zeit validiert den Inhalt erneut, weil eine Vorlage, die ausgibt, wann die Tatsache eintrat, sie aus dem Inhalt liest, wo die Zeit, zu der ein Beitrag losgeht, für sie eingetragen ist (occurredAt, nur bei einer Vorlage, die eine nimmt).

POST /v1/queues/{id}/packages/{packageId}/delete entfernt einen Beitrag aus der Liste und antwortet mit { "ok": true }.

POST /v1/queues/{id}/delete entfernt die Liste und jeden Beitrag darauf, meldet die Kanäle ab, die sie empfingen, samt den Veröffentlichungsaufträgen, die sie daraus erstellt haben, und ihren Clips. Die Antwort sagt, wie viele Kanäle:

{ "ok": true, "removedFromChannels": 3 }

Eine Liste veröffentlichen lassen​

Eine Beitragsliste anzulegen veröffentlicht von sich aus nichts. Ein Kanal muss sie abonnieren, mit kind: "QUEUE"; siehe Kanäle. Ein Beitrag geht los, ob jemand empfängt oder nicht, und einer, den niemand empfing, hat nichts erzeugt: Sein outcome sagt channels: 0. Der Kanal legt für eine Liste nichts fest: Jeder Beitrag wählt seine eigene Vorlage, seinen Zuschnitt und Build. Ob ein Beitrag dann auf eine Freigabe wartet, ist die eigene Freigabeeinstellung des Kanals, wie bei jeder anderen Quelle.

Was jeder Beitrag neben seinem Clip sagt, ist das, was in seinen metaData geschrieben wurde: der Titel und die Beschreibung in der Länge, die zur Plattform jedes empfangenden Kanals passt (die vier Längen und welche Plattformen welche nehmen, stehen unter Vorlagen und Formate). Schreiben Sie die Längen, die Ihre Kanäle brauchen; eine weggelassene wird aus der nächstkürzeren geschriebenen gefüllt, sonst aus der nächstlängeren. Für einen manuellen Beitrag wird nichts hinter dem Rücken des Verfassers geschrieben: Eine leer gelassene Beschreibung oder leere Hashtags gehen leer hinaus. Nur ein leerer Titel wird gefüllt, aus dem eigenen Titel des Clips (sein clipData title und label oder headline) oder dem Namen der Liste, wo es keinen gibt, weil manche Plattformen kein Video ohne einen annehmen.

Einen Beitrag erneut erstellen​

GET /v1/jobs/{id}/reuse antwortet mit dem, woraus ein fertiger Beitrag gemacht wurde. Senden Sie seine templateId, variant als templateVariant, pinnedVersion als templateVersion und data an POST /v1/queues/{id}/packages, mit einem title und einem scheduledFor, und der Beitrag geht mit allem, was Sie geändert haben, erneut hinaus; bei einem Beitrag, der aus einer Liste kam, nennt queueId die Liste. Im Dashboard öffnet Wiederverwenden auf der Seite Beiträge, Als neuer Beitrag, Beitrag hinzufügen im Beitragseditor mit allem ausgefüllt.

Die nächsten Wochen planen​

GET /v1/queues/{id}/plan antwortet, wann die Beiträge der nächsten Wochen dieser Liste hinausgehen können und wie viele hineinpassen: worauf der Inhaltsplan eines Assistenten aufbaut (reelwire_plan_posts). Es liest und ändert nichts, und es sagt nie, was ein Beitrag sagen soll.

AbfrageWas es ist
weeksWie viele Wochen im Voraus, 1 bis 13. Standard 12.
fromWann der Plan beginnt, ISO 8601. Standard jetzt.
timeZoneWo das Publikum lebt, eine IANA-Zone wie Europe/Berlin. Standard ist eine Vermutung aus der Sprache des ersten empfangenden Kanals, beantwortet mit timeZoneAssumed: true.
postsPerWeek1 bis 21. Standard ist, was das Kontingent bezahlt, höchstens drei.
daysWochentage, Mon,Wed,Fri oder 1,3,5, statt postsPerWeek gleichmäßig zu verteilen.
timesOrtszeiten, HH:MM zwischen 06:00 und 20:00, höchstens drei. Standard 09:00.

Jeder Slot hält drei Regeln ein. Das Kontingent, Zeitraum für Zeitraum: Ein Beitrag wird einmal für jeden Kanal gerendert, der die Liste empfängt, und was ein Zeitraum übrig hat, sind seine Videos abzüglich der verbrauchten, abzüglich dessen, was die Kanäle schon kommen haben (die Einträge des Veröffentlichungskalenders, Feeds und Listen gleichermaßen), abzüglich dessen, was der Plan hinzufügt. Die Steigerung, je Kanal und Ortstag: höchstens ein Beitrag am Tag in der ersten Woche eines Kanals, zwei in Woche zwei und drei, drei ab Woche vier, gezählt ab seinem ersten Beitrag. Tageslicht: Jede Zeit liegt zwischen 06:00 und 20:00, wo das Publikum lebt. Ein Slot, der eine bricht, steht in dropped, mit why (allowance oder ramp).

{
"queue": { "id": "01M2SQRG1HVVSB4P1D04WT0T8Z", "name": "Default post list", "enabled": true },
"window": { "from": "2026-10-26T00:00:00.000Z", "to": "2027-01-18T00:00:00.000Z", "weeks": 12 },
"timeZone": "Europe/Berlin",
"timeZoneAssumed": false,
"rendersPerPost": 1,
"postsPerWeek": 3,
"slots": [
{ "at": "2026-10-26T08:00:00.000Z", "local": "Mon 2026-10-26 09:00", "week": 1 },
{ "at": "2026-10-28T08:00:00.000Z", "local": "Wed 2026-10-28 09:00", "week": 1 }
],
"dropped": [],
"droppedCount": { "allowance": 0, "ramp": 0 },
"periods": [
{ "start": "2026-10-12T09:30:00.000Z", "end": "2026-11-12T09:30:00.000Z", "allowance": 15, "used": 2, "booked": 0, "planned": 5, "left": 8, "morePosts": 8 }
],
"channels": [
{ "id": "01M1W0W9Q1ZB5Y8WQF8R8C3V7K", "name": "Default channel", "locale": "de", "firstPostAt": null, "weekAtStart": 1, "postsPerDayAtStart": 1 }
]
}

Einen ganzen Plan auf einmal schreiben​

POST /v1/queues/{id}/packages/batch nimmt posts, eine Liste von bis zu 100, jeder mit den Feldern eines einzelnen Beitrags (title, templateId, templateVariant, templateVersion, scheduledFor, data). Jeder Beitrag wird genau wie einer geprüft, und nichts wird geschrieben, wenn nicht alle passen: Eine Ablehnung ist ein 400, dessen details jeden Beitrag, der nicht passt, mit seiner Nummer nennen, /posts/3/clipData/title. Die Antwort ist packages, die geschriebenen Beiträge in zeitlicher Reihenfolge, mit einem 201.

Häufige Fehler​

Auf einen Validierungsfehler beim Losgehen warten. Es gibt keinen. Der Inhalt wird beim Speichern geprüft, gegen den Build, mit dem er gerendert würde.

In die Vergangenheit planen, um jetzt zu veröffentlichen. Es wird abgelehnt. Verwenden Sie "now".

locales neben data senden. Sprachkopien gehören in data, wo die Vorlage sie validiert.

Einen Beitrag bearbeiten, der schon losgegangen ist. Ein 409. Erstellen Sie einen neuen Beitrag.

templateVersion festlegen und vergessen. Eine Festlegung auf einen exakten Build folgt neuen nicht mehr. Senden Sie "latest" oder lassen Sie es weg, sofern Sie keinen Grund haben.

Eine Liste löschen, um aufzuräumen. Jeder Kanal, der sie empfängt, verliert dieses Abonnement, und die Veröffentlichungsaufträge, die sie erstellt hat, gehen mit. Prüfen Sie zuerst listeners, oder setzen Sie enabled: false, was die Abonnements behält.

Eine Liste ausschalten, um sie zu pausieren. Ein Beitrag, der fällig wird, während die Liste aus ist, geht an niemanden los und wird später nicht gesendet. Verschieben Sie stattdessen die Zeit des Beitrags, oder brechen Sie ihn ab.