Introduction
API des aaronflash-Dashboards. Quelle der Wahrheit für api/openapi.yaml und das generierte TypeScript-SDK.
Alle Endpoints liegen unter `/api/v1` und antworten in JSON. Authentifiziert
wird über die Sanctum-SPA-Session: erst `GET /sanctum/csrf-cookie`, dann
`POST /api/v1/auth/login` — danach tragen Session-Cookie und `X-XSRF-TOKEN`
die Anmeldung. Brand-scoped Endpoints erwarten zusätzlich den Header
`X-Brand-Slug` (`dkd` oder `happyhug`).
<aside>Diese Doku wird aus dem Laravel-Code generiert (`make api`) — nicht von Hand pflegen.</aside>
Authenticating requests
To authenticate requests, include a Cookie header with the value "aaronflash_session={SESSION_COOKIE}".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
Session-Cookie aus dem Login (POST /api/v1/auth/login nach GET /sanctum/csrf-cookie). Das generierte SDK erledigt das über credentials: include.
Auth
Anmeldung des Dashboards über die Sanctum-SPA-Session: erst
GET /sanctum/csrf-cookie, dann Login — danach trägt das Session-Cookie
die Authentifizierung.
Login
Meldet mit E-Mail und Passwort an und startet die Session. Vorher muss
der Client GET /sanctum/csrf-cookie geholt und den X-XSRF-TOKEN
mitgeschickt haben.
Example request:
curl --request POST \
"http://localhost:8000/api/v1/auth/login" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"email\": \"gbailey@example.net\",
\"password\": \"|]|{+-\"
}"
const url = new URL(
"http://localhost:8000/api/v1/auth/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "gbailey@example.net",
"password": "|]|{+-"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"user": {
"id": 1,
"name": "Aaron",
"email": "aaron@example.com"
}
}
Example response (422):
{
"message": "Diese Zugangsdaten passen zu keinem Konto.",
"errors": {
"email": [
"Diese Zugangsdaten passen zu keinem Konto."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
user
object
Die angemeldete Nutzerin.
id
integer
name
string
email
string
Logout
requires authentication
Beendet die Session und macht das Cookie ungültig.
Example request:
curl --request POST \
"http://localhost:8000/api/v1/auth/logout" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/auth/logout"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (204):
Empty response
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Current user
requires authentication
Die angemeldete Nutzerin der laufenden Session.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/auth/me" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/auth/me"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"user": {
"id": 1,
"name": "Aaron",
"email": "aaron@example.com"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
user
object
Die angemeldete Nutzerin.
id
integer
name
string
email
string
Brain
Der Wissens-Store einer Marke, read-only fürs Dashboard: die Einträge, aus
denen Flashy seine Entwürfe baut, und der Status des trybe-Brain-Anschlusses.
Gepflegt wird der Store über die Seeds — es gibt bewusst keine
Schreib-Endpunkte. Alle Routen sind brand-scoped (X-Brand-Slug).
List brain entries
requires authentication
Die Wissens-Einträge der aktiven Marke, sortiert nach Art und Titel. Seitenweise zu 50.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/brain/entries?kind=faq&page=1" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/brain/entries"
);
const params = {
"kind": "faq",
"page": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"kind": "faq",
"title": "Ab wann sind die Tropfen geeignet?",
"body": "Ab dem ersten Lebenstag — die Dosierung steht auf der Packung.",
"source": "happyhug/desk-faq.md"
}
],
"links": {
"first": "https://aaronflash.test/api/v1/brain/entries?page=1",
"last": "https://aaronflash.test/api/v1/brain/entries?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Zurück",
"active": false
}
],
"path": "https://aaronflash.test/api/v1/brain/entries",
"per_page": 50,
"to": 1,
"total": 1
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object[]
id
integer
kind
string
product, fact, faq, study oder service.
title
string
body
string
Der Wissens-Text.
source
string
Herkunft des Eintrags (Seed-Datei).
Get brain status
requires authentication
Woher das Wissen der aktiven Marke kommt: wie viele lokale Einträge es
gibt, welcher trybe-Brain-Treiber läuft und ob das trybe Brain für
diese Marke gerade antwortet. trybeConnected=false heißt: die Marke
arbeitet rein mit dem lokalen Store — kein Fehler, der Normalfall für
DKD.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/brain/status" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/brain/status"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"entryCount": 42,
"trybeDriver": "off",
"trybeConnected": false
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
entryCount
integer
Anzahl der lokalen Wissens-Einträge.
trybeDriver
string
Konfigurierter Treiber (off, fake oder live).
trybeConnected
boolean
Ob das trybe Brain für diese Marke konfiguriert ist und antwortet.
Brands
Die Marken des Dashboards. Der Brand-Switcher lädt sie einmal; der slug
wandert danach als X-Brand-Slug in jede brand-scoped Anfrage.
List brands
requires authentication
Alle Marken, zwischen denen das Dashboard umschalten kann.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/brands" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/brands"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 1,
"slug": "dkd",
"name": "DeinKinderdoc"
},
{
"id": 2,
"slug": "happyhug",
"name": "happyhug"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object[]
id
integer
slug
string
Stabiler Schlüssel, Wert für X-Brand-Slug.
name
string
Anzeigename.
Flashy
KI-Entwürfe für den Posteingang: erzeugen, regenerieren, übernehmen. Die KI
erzeugt Entwürfe, ein Mensch sendet — Kein Auto-Send (VISION §9). Alle
Routen sind brand-scoped (X-Brand-Slug).
Generate draft
requires authentication
Erzeugt einen Antwort-Entwurf für den Thread — aus Tonprofil und
Wissens-Store der Marke (plus trybe Brain, wenn an). Ein erneuter
Aufruf regeneriert: neuer Entwurf mit generation+1, die älteren
bleiben stehen. Mit Treiber anthropic läuft das NUR, wenn die Marke
llm_enabled=true hat UND ein API-Key gesetzt ist — sonst 409, und
kein Nachrichteninhalt verlässt das System (VISION §9).
Example request:
curl --request POST \
"http://localhost:8000/api/v1/conversations/3/drafts" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/conversations/3/drafts"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (201):
{
"data": {
"id": 1,
"conversationId": 3,
"body": "Danke dir für deine Nachricht!\n\nMelde dich gern, wenn noch etwas offen ist.",
"model": "fake",
"generation": 1,
"acceptedAt": null,
"createdAt": "2026-09-08T14:30:00+02:00"
}
}
Example response (404, Fremde Marke oder unbekannte Id):
{
"message": "Diesen Thread gibt es hier nicht."
}
Example response (409, Treiber anthropic, aber llm_enabled=false):
{
"message": "KI-Entwürfe über Anthropic sind für diese Marke ausgeschaltet. Solange das so ist, verlässt kein Nachrichteninhalt das System. Einschalten geht erst, wenn die Rechtsgrundlage geklärt ist (Art. 9 DSGVO) — bis dahin steht dir der Fake-Treiber zur Verfügung.",
"reason": "llm_disabled"
}
Example response (502, Anthropic nicht erreichbar):
{
"message": "Anthropic hat nicht geantwortet — der Entwurf wurde nicht erzeugt. Versuch es gleich noch einmal.",
"reason": "driver_failed"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
Der neue Entwurf.
id
integer
conversationId
integer
body
string
Der Entwurfstext.
model
string
Erzeugendes Modell (fake oder der Anthropic-Modellname).
generation
integer
1 beim ersten Entwurf, +1 je Regeneration.
acceptedAt
string
Immer null — übernommen wird über den Accept-Endpunkt.
createdAt
string
Accept draft
requires authentication
Markiert den Entwurf als übernommen (acceptedAt). Es wird NICHTS
gesendet — der Text wandert in den Composer, und der Mensch sendet über
den Inbox-Endpunkt (Kein Auto-Send, VISION §9). Ein zweites Übernehmen
ändert den Zeitstempel nicht.
Example request:
curl --request POST \
"http://localhost:8000/api/v1/drafts/1/accept" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/drafts/1/accept"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"conversationId": 3,
"body": "Danke dir für deine Nachricht!\n\nMelde dich gern, wenn noch etwas offen ist.",
"model": "fake",
"generation": 1,
"acceptedAt": "2026-09-08T14:31:00+02:00",
"createdAt": "2026-09-08T14:30:00+02:00"
}
}
Example response (404, Fremde Marke oder unbekannte Id):
{
"message": "Diesen Entwurf gibt es hier nicht."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
Der Entwurf mit gesetztem acceptedAt.
Get flashy settings
requires authentication
Der Stand der Marke: ist der LLM-Zugriff frei (llmEnabled), und
welcher Entwurfs-Treiber läuft (draftDriver). Solange
llmEnabled=false, verlässt kein Nachrichteninhalt das System —
Entwürfe kommen dann nur vom Fake-Treiber.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/flashy/settings" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/flashy/settings"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"llmEnabled": false,
"draftDriver": "fake"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
llmEnabled
boolean
Der DSGVO-Art.-9-Schalter der Marke; Default false.
draftDriver
string
Konfigurierter Entwurfs-Treiber (fake oder anthropic).
Get tone profile
requires authentication
Das Tonprofil der aktiven Marke — Prosa-Stimme, Beispiel-Formulierungen und verbotene Formulierungen.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/flashy/tone-profile" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/flashy/tone-profile"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"voice": "Warm, auf Augenhöhe, per Du. Fachbegriffe werden erklärt statt vorausgesetzt.",
"beispiele": [
"Danke dir für deine Nachricht!"
],
"verboteneFormulierungen": [
"Sehr geehrte Damen und Herren"
],
"updatedAt": "2026-09-08T10:00:00+02:00"
}
}
Example response (404, Noch kein Profil):
{
"message": "Für diese Marke ist noch kein Tonprofil angelegt."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
id
integer
voice
string
Prosa-Beschreibung der Marken-Stimme.
beispiele
string[]
Beispiel-Formulierungen.
verboteneFormulierungen
string[]
Formulierungen, die Entwürfe meiden.
updatedAt
string
Letzte Änderung (ISO 8601).
Update tone profile
requires authentication
Ersetzt das Tonprofil der aktiven Marke komplett (PUT). Gibt es noch keines, wird es angelegt. Wirkt ab dem nächsten Entwurf — bestehende Entwürfe bleiben, wie sie sind.
Example request:
curl --request PUT \
"http://localhost:8000/api/v1/flashy/tone-profile" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"voice\": \"Warm, auf Augenhöhe, per Du. Fachbegriffe werden erklärt statt vorausgesetzt.\",
\"beispiele\": [
\"Danke dir für deine Nachricht!\"
],
\"verbotene_formulierungen\": [
\"Sehr geehrte Damen und Herren\"
]
}"
const url = new URL(
"http://localhost:8000/api/v1/flashy/tone-profile"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"voice": "Warm, auf Augenhöhe, per Du. Fachbegriffe werden erklärt statt vorausgesetzt.",
"beispiele": [
"Danke dir für deine Nachricht!"
],
"verbotene_formulierungen": [
"Sehr geehrte Damen und Herren"
]
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"voice": "Warm, auf Augenhöhe, per Du. Fachbegriffe werden erklärt statt vorausgesetzt.",
"beispiele": [
"Danke dir für deine Nachricht!"
],
"verboteneFormulierungen": [
"Sehr geehrte Damen und Herren"
],
"updatedAt": "2026-09-08T10:05:00+02:00"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
Das gespeicherte Profil.
Inbox
Der Posteingang einer Marke: Threadliste, Thread mit Kontakt und Verlauf,
Zuweisen und Erledigen. Alle Routen sind brand-scoped (X-Brand-Slug).
List conversations
requires authentication
Die Threadliste, sortiert nach window_expires_at aufsteigend — was
zuerst abläuft, steht oben (VISION §4). Threads ohne Fenster (noch
keine eingehende Nachricht) kommen ans Ende. Seitenweise zu 50.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/conversations?unanswered=1&status=open&assignee_id=1&page=1" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/conversations"
);
const params = {
"unanswered": "1",
"status": "open",
"assignee_id": "1",
"page": "1",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"id": 3,
"status": "open",
"unanswered": true,
"assigneeId": null,
"windowExpiresAt": "2026-09-06T09:12:00+02:00",
"lastMessageAt": "2026-09-05T09:12:00+02:00",
"contact": {
"id": 3,
"igUserId": "8900000000000003",
"username": "papa.jonas",
"followerCount": 87,
"notes": null
},
"lastMessage": {
"id": 3,
"direction": "in",
"kind": "text",
"text": "Danke für den Tipp mit dem Vernebler, hat super geholfen!",
"sentAt": "2026-09-05T09:12:00+02:00",
"attachments": null
}
}
],
"links": {
"first": "https://aaronflash.test/api/v1/conversations?page=1",
"last": "https://aaronflash.test/api/v1/conversations?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Zurück",
"active": false
}
],
"path": "https://aaronflash.test/api/v1/conversations",
"per_page": 50,
"to": 1,
"total": 1
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object[]
Threads mit Kontakt und jüngster Nachricht als Vorschau.
id
integer
status
string
open oder done.
unanswered
boolean
Wahr, wenn die jüngste Nachricht vom Kontakt kam.
assigneeId
integer
Zugewiesene Nutzerin, sonst null.
windowExpiresAt
string
Ende des 24-h-Antwortfensters (ISO 8601), null ohne eingehende Nachricht.
lastMessageAt
string
Zeitpunkt der jüngsten Nachricht (ISO 8601).
contact
object
Der Kontakt hinter dem Thread.
lastMessage
object
Die jüngste Nachricht als Vorschau.
Get conversation
requires authentication
Ein Thread mit Kontakt und komplettem Verlauf, älteste Nachricht zuerst.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/conversations/3" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/conversations/3"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 3,
"status": "open",
"unanswered": true,
"assigneeId": null,
"windowExpiresAt": "2026-09-06T09:12:00+02:00",
"lastMessageAt": "2026-09-05T09:12:00+02:00",
"contact": {
"id": 3,
"igUserId": "8900000000000003",
"username": "papa.jonas",
"followerCount": 87,
"notes": null
},
"messages": [
{
"id": 3,
"direction": "in",
"kind": "text",
"text": "Danke für den Tipp mit dem Vernebler, hat super geholfen!",
"sentAt": "2026-09-05T09:12:00+02:00",
"attachments": null
}
]
}
}
Example response (404, Fremde Marke oder unbekannte Id):
{
"message": "Diesen Thread gibt es hier nicht."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
id
integer
status
string
open oder done.
unanswered
boolean
assigneeId
integer
Zugewiesene Nutzerin, sonst null.
windowExpiresAt
string
Ende des 24-h-Antwortfensters (ISO 8601).
lastMessageAt
string
contact
object
messages
object[]
Der Verlauf, älteste zuerst.
Update conversation
requires authentication
Zuweisen und Erledigen: assignee_id setzt oder löst die Zuweisung
(null = niemand), status schaltet zwischen open und done.
Example request:
curl --request PATCH \
"http://localhost:8000/api/v1/conversations/3" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"status\": \"done\",
\"assignee_id\": 1
}"
const url = new URL(
"http://localhost:8000/api/v1/conversations/3"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"status": "done",
"assignee_id": 1
};
fetch(url, {
method: "PATCH",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"data": {
"id": 3,
"status": "done",
"unanswered": false,
"assigneeId": 1,
"windowExpiresAt": "2026-09-06T09:12:00+02:00",
"lastMessageAt": "2026-09-05T09:12:00+02:00",
"contact": {
"id": 3,
"igUserId": "8900000000000003",
"username": "papa.jonas",
"followerCount": 87,
"notes": null
}
}
}
Example response (404, Fremde Marke oder unbekannte Id):
{
"message": "Diesen Thread gibt es hier nicht."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
Der Thread nach der Änderung, mit Kontakt.
Guess conversation context
requires authentication
Mögliche Bezüge der ERSTEN eingehenden Nachricht des Threads: Stories, die zu diesem Zeitpunkt liefen, und die jüngsten Beiträge davor. Leer, wenn das Konto nicht verbunden ist oder Meta nichts liefert.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/conversations/3/context-guess" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/conversations/3/context-guess"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"type": "story",
"label": "Story von 06:00",
"permalink": "https://www.instagram.com/stories/fake/1",
"postedAt": "2026-09-09T06:00:00+02:00"
},
{
"type": "media",
"label": "Fieber bei Kindern: wann senken, wann abwarten?",
"permalink": "https://www.instagram.com/reel/fake1/",
"postedAt": "2026-09-09T05:00:00+02:00"
}
]
}
Example response (404, Fremde Marke oder unbekannte Id):
{
"message": "Diesen Thread gibt es hier nicht."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object[]
Kandidaten, wahrscheinlichste zuerst.
type
string
story oder media.
label
string
Anzeigetext (Caption-Auszug bzw. Story + Uhrzeit).
permalink
string
Link zum Inhalt auf Instagram, sonst null.
postedAt
string
Veröffentlichungszeitpunkt (ISO 8601).
Send message
requires authentication
Sendet eine Text-Antwort in den Thread — über die Graph API, im Namen
des verbundenen Kontos. Das 24-h-Fenster ist bewusst KEIN Guard vorm
Senden (VISION §4): ob es offen ist, entscheidet Meta, und Metas
Ablehnung kommt als 422 mit reason und Klartext zurück.
Example request:
curl --request POST \
"http://localhost:8000/api/v1/conversations/3/messages" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--data "{
\"text\": \"Gern! Melde dich jederzeit.\"
}"
const url = new URL(
"http://localhost:8000/api/v1/conversations/3/messages"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"text": "Gern! Melde dich jederzeit."
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"data": {
"id": 9,
"direction": "out",
"kind": "text",
"text": "Gern! Melde dich jederzeit.",
"attachments": null,
"sentAt": "2026-09-08T14:30:00+02:00"
}
}
Example response (404, Fremde Marke oder unbekannte Id):
{
"message": "Diesen Thread gibt es hier nicht."
}
Example response (422, Meta lehnt ab (z. B. Fenster abgelaufen)):
{
"message": "Fake wie Meta (#10): Das 24-Stunden-Fenster ist abgelaufen — diese Nachricht wird nicht mehr zugestellt.",
"reason": "outside_window"
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
Die gesendete Nachricht, wie sie im Verlauf steht.
id
integer
direction
string
Immer out.
kind
string
Immer text.
text
string
sentAt
string
Das Instagram-Konto einer Marke: Verbinden über den Instagram-Login (OAuth), Status einsehen, Trennen. Genau ein Konto je Marke.
Rückweg von Instagram
Meta schickt den Browser hierher — ohne Sitzung, ohne Marken-Header:
die Marke steht im state, sonst nirgends. Die Antwort ist immer eine
Weiterleitung ins Dashboard (?connected=1|0&reason=…) — ein Mensch
vor dem Browser soll kein JSON sehen, auch nicht bei einem Fehler.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/instagram/callback?code=AQD3f0a9c1a&state=eyJpdiI6%E2%80%A6&error=access_denied" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/instagram/callback"
);
const params = {
"code": "AQD3f0a9c1a",
"state": "eyJpdiI6…",
"error": "access_denied",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (302, Verbunden):
Example response (302):
Show headers
cache-control: no-cache, private
location: http://localhost:3000/einstellungen?connected=0&reason=invalid_state
content-type: text/html; charset=utf-8
x-ratelimit-limit: 60
x-ratelimit-remaining: 59
access-control-allow-origin: http://localhost:3000
access-control-allow-credentials: true
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0;url='http://localhost:3000/einstellungen?connected=0&reason=invalid_state'" />
<title>Redirecting to http://localhost:3000/einstellungen?connected=0&reason=invalid_state</title>
</head>
<body>
Redirecting to <a href="http://localhost:3000/einstellungen?connected=0&reason=invalid_state">http://localhost:3000/einstellungen?connected=0&reason=invalid_state</a>.
</body>
</html>
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Instagram-Login starten
requires authentication
Der Server leitet NICHT weiter: er gibt die Zustimmungs-Adresse zurück,
und das Dashboard wechselt das Fenster. Der state bindet Marke und
Mensch an den Rückweg.
Response
Response Fields
data
object
authorizeUrl
string
Die Dialog-Adresse für das Browser-Fenster.
Verbundenes Konto
requires authentication
Das Instagram-Konto der Marke mit Token-Ablauf und Webhook-Status — der Access-Token selbst bleibt im Backend.
Example request:
curl --request GET \
--get "http://localhost:8000/api/v1/instagram/account" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/instagram/account"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"id": 1,
"igUserId": "17841400000000001",
"username": "deinkinderdoc",
"tokenExpiresAt": "2026-11-07T10:00:00+01:00",
"connectedAt": "2026-09-08T10:00:00+02:00",
"webhookActive": false,
"lastError": null
}
}
Example response (404, Nicht verbunden):
{
"message": "Für diese Marke ist kein Instagram-Konto verbunden."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Response
Response Fields
data
object
id
integer
igUserId
string
Id des professionellen Kontos bei Meta.
username
string
tokenExpiresAt
string
Wann der langlebige Token abläuft (ISO 8601).
connectedAt
string
webhookActive
boolean
lastError
string
Letzter Fehler des Token-Refreshs, sonst null.
Konto trennen
requires authentication
Löscht Verbindung und Token der Marke. Neu verbinden geht jederzeit über den Instagram-Login.
Example request:
curl --request DELETE \
"http://localhost:8000/api/v1/instagram/account" \
--header "Cookie: aaronflash_session={SESSION_COOKIE}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"const url = new URL(
"http://localhost:8000/api/v1/instagram/account"
);
const headers = {
"Cookie": "aaronflash_session={SESSION_COOKIE}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (204, Getrennt):
Empty response
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.