Mumro Docs docs.mumro.io
Dla uzytkownika Technologia Mozliwosci API API

Produkt, integracje i technologia

Dokumentacja Mumro

Przewodnik po aplikacji dla uzytkownikow, opis architektury dla deweloperow oraz stabilna referencja publicznego API.

POST /api/website-articles
{
  "site_id": 12,
  "title": "Artykul przez API",
  "content_html": "<h2>Wprowadzenie</h2><p>Tresc...</p>",
  "metadata_json": {
    "source_record_id": "article-123"
  }
}

Dla uzytkownika

Jak dziala Mumro

Mumro laczy konta spolecznosciowe, planowanie publikacji, moderacje komentarzy, analityke oraz narzedzia wspierane przez AI w jednym panelu.

1

Podlacz konta

Dodaj profile w sekcji Konta i sprawdz, czy synchronizacja pobiera publikacje, komentarze oraz metryki.

2

Przygotuj publikacje

Utworz tresc, wybierz konta, dodaj media i zaplanuj termin albo zapisz material jako szkic.

3

Monitoruj wyniki

Kontroluj kolejke, opublikowane tresci, komentarze i analityke. Bledy publikacji wymagaja sprawdzenia przed ponowieniem.

Laczenie Facebooka i Instagrama

Jedna przestrzen moze miec jedna strone Facebook i jedno profesjonalne konto Instagram. Jezeli jedno konto logowania Meta zarzadza kilkoma markami, wybierz dokladnie jeden profil odpowiadajacy aktywnej przestrzeni. Gdy Meta zwroci kilka profili tego samego typu, Mumro nie doda zadnego z nich i poprosi o ponowienie.

ObszarDo czego sluzyCo warto kontrolowac
Pulpit Szybki obraz aktywnosci organizacji. Alerty, ostatnie publikacje i stan kont.
Plan i kolejka Przygotowanie i harmonogramowanie tresci. Termin, strefa czasowa, konta oraz media.
Opublikowane Historia wyslanych materialow i ich statusow. Bledy czesciowe, linki do platform i ponowienia.
Komentarze Moderacja i obsluga reakcji odbiorcow. Konto, autor, tresc i stan obslugi.
Analityka Porownanie wynikow kont i publikacji. Zakres dat, wybrane konta i znaczenie metryk.
Konta Polaczenia z obslugiwanymi platformami. Wygasle uprawnienia i czas ostatniej synchronizacji.
Harmonogramy Powtarzalne zasady publikowania. Dni, godziny, aktywnosc i docelowe konta.
WWW i generatory AI Tworzenie artykulow, postow i materialow pomocniczych. Szkic przed publikacja oraz reczna weryfikacja tresci.
Wazne

Widoczne funkcje zaleza od roli uzytkownika, konfiguracji organizacji i wlaczonych modulow. Pelny przewodnik znajduje sie takze w pliku docs/user-guide.md.

Cykliczne karuzele Instagram

Autopilot karuzel

Mumro moze regularnie zebrac zrodla z internetu lub wlasnego portalu, przygotowac pionowa karuzele, opis i hashtagi, a potem zapisac szkic, uzyc najblizszego slotu albo opublikowac.

1

Ustal serie

Wybierz temat, kanal Instagram, jezyk, ton oraz cykl od 1 do 90 dni.

2

Wybierz zrodlo

Uzyj profilu RSS i domen, wyszukiwarki, najnowszych artykulow portalu, jednego artykulu albo briefu evergreen.

3

Najpierw podejrzyj

Podglad zawsze tworzy szkic, nie publikuje i nie przesuwa kolejnego terminu cyklu.

Wspolne profile zrodel

Artykuly, rolki i karuzele korzystaja z tych samych profili RSS/Atom, oficjalnych i preferowanych domen oraz progow jakosci. Gotowy profil AI mozna dodac jednym przyciskiem w Ustawieniach - Zrodla informacji, edytowac, duplikowac i sprawdzic bez generowania tresci. Test pokazuje osiagniete progi oraz konkretne daty i linki do publikacji. Profil z RSS dziala bez Tavily; Brave Search, SerpAPI albo Tavily moze rozszerzyc wyniki w trybie hybrydowym. Kazdy adres RSS jest osobnym torem researchu, nawet gdy kilka kanalow pochodzi z tej samej domeny.

Aktualny zakres

Autopilot renderuje wlasne slajdy 1080 x 1350 albo kwadratowe 1080 x 1080, moze wygenerowac okladke AI albo wykorzystac grafiki wyrozniajace artykulow z aktywnej przestrzeni. Slajdy tematyczne moga dostac do czterech bezpiecznie pobranych obrazow dopasowanych zrodel, a badge z liczba lub nazwa modelu pojawia sie tylko wtedy, gdy fakt nie wystepuje juz w tekscie. Brak obrazu lub blad pliku uruchamia bezpieczny szablon i nie przerywa generowania. Nie kopiuje dowolnych zdjec, nie wykonuje obcego HTML ani automatycznych screenshotow stron. Artykul mozna przekazac do karuzeli bezposrednio z edytora Artykuly WWW i sprawdzic w podgladzie przed publikacja. Pelna instrukcja znajduje sie w docs/social-autopilot.md.

Jedna domena, jedno miejsce konfiguracji

Analityka, chatbot i artykuly

Ekran Strona WWW → Konfiguracja strony laczy stan integracji, wspolny kod instalacyjny oraz polaczenie publikacji artykulow dla wybranej domeny.

1

Wybierz strone

Rekord strony jest wspolny dla analityki, chatbota i docelowego CMS.

2

Polacz chatbota

Wybierz bota i aktywuj go dla domeny. Mumro zachowa jego pozostale dozwolone domeny.

3

Zapisz i testuj CMS

Skonfiguruj WordPress albo wlasny endpoint i sprawdz polaczenie przed publikacja.

Wspolny kod instalacyjny - wklej przed </body>
<script async src="https://app.mumro.io/api/website-analytics/script.js?p=wa_REPLACE_ME"></script>
<script async src="https://app.mumro.io/api/chatbot/widget.js?b=cb_pub_REPLACE_ME"></script>
To sa dwa rozne skrypty

Analityka korzysta z website-analytics/script.js?p=wa_..., a chatbot z chatbot/widget.js?b=cb_pub_.... Dwa identyczne kody widgetu nie wlaczaja analityki. Zawsze kopiuj aktualny blok z Konfiguracji strony.

Instrukcja dla uzytkownika

Artykuly WWW w Mumro

Modul Artykuly WWW jest prostym CMS-em. Artykul najpierw powstaje jako lokalny szkic w Mumro, a dopiero wybrana akcja wysyla jego aktualna wersje do WordPressa albo wlasnej integracji strony.

1

Dodaj i wybierz strone

Wybierz domene w Konfiguracji strony. Kazdy artykul jest przypisany do jednej strony.

2

Polacz CMS

W Konfiguracji strony ustaw WordPress albo wlasny endpoint i uzyj przycisku Testuj.

3

Napisz i opublikuj

Zapisz lokalny szkic, wyslij szkic do CMS, zaplanuj publikacje albo publikuj od razu.

Konfiguracja WordPress

Podaj adres glownej strony, uzytkownika WordPress i jego Application Password.

Nie uzywaj zwyklego hasla logowania. Uzytkownik WordPress musi miec prawo tworzenia i edycji wpisow.

Wlasna integracja

Podaj endpoint HTTPS przygotowany przez dewelopera i wspolny Bearer token.

Na stronie klienta nie jest potrzebne logowanie uzytkownika. Endpoint uwierzytelnia Mumro na podstawie sekretnego tokenu.

Co mozna umiescic w tresci

Edytor obsluguje akapity, naglowki H2/H3, pogrubienie, kursywe, cytaty, listy, linki, obrazy do 20 MB, tryb HTML oraz osadzenia wideo z YouTube, Vimeo, Facebooka, TikToka i Dailymotion. Ostateczny wyglad i dopuszczalny HTML zaleza od docelowego CMS i stylow strony.

AkcjaCo sie dzieje
Zapisz szkicZapisuje artykul tylko lokalnie w Mumro.
Wyslij jako szkicTworzy albo aktualizuje zdalny szkic w CMS.
Zaplanuj w CMSWymaga przyszlej daty i wysyla status future.
Publikuj terazTworzy albo aktualizuje opublikowany wpis.
Wykorzystaj artykul ponownie

Z jednego miejsca pod edytorem utworzysz rolke tekstowa, karuzele ze szkicowym podgladem albo pojedynczy post promujacy artykul. Tryb Portal moze cyklicznie pobierac kolejne, jeszcze niewykorzystane wpisy z wybranej strony. Promocja social w trybie smart daje Instagramowi i Facebookowi pelna karuzele, X i LinkedIn pojedyncza grafike, a link umieszcza w odpowiednim miejscu.

Pelny autopilot: artykul przed postem

W Autopilocie artykulow wlacz Pelny autopilot, aby zachowac kolejnosc research → artykul → grafiki → publikacja artykulu → posty social. Kazdy kanal ma osobny job i osobny status, a X przy recznej karuzeli otrzymuje najwyzej cztery slajdy. Lokalny lub zdalny szkic nie uruchamia promocji, dopoki artykul nie stanie sie publiczny.

Jeden jezyk publikacji i osobne tlumaczenia artykulu

W sekcji Jezyki publikacji Autopilota artykulow ustaw jezyk glowny. Steruje on jednoczesnie trescia artykulu, napisami na grafikach, opisami postow i wezwaniem do przejscia do artykulu. Dodatkowe jezyki tworza osobne wersje tylko artykulu: nie powielaja grafik ani publikacji social. Powiazane wersje na mumro.io prowadza do siebie przez przelacznik jezyka.

Podglad kosztu sumuje article.generate, kazde article.translate, opis social i opcjonalny obraz AI. Dla wbudowanych kredytow domyslna cena jednego tlumaczenia wynosi 75 kredytow. Zadanie asynchroniczne rezerwuje kredyty przed startem, rozlicza je po sukcesie i zwalnia po bledzie.

Artykul newsowy wymaga dzialajacego researchu.

Autopilot pozwala wybrac profil RSS i domen albo Tavily, Brave Search czy SerpAPI. Klucz wyszukiwarki dziala niezaleznie od modelu piszacego, a profil z RSS nie wymaga takiego klucza. Nowy formularz domyslnie wybiera pierwszy aktywny profil i limit 10 zrodel. Glowny brief, dodatkowe zapytania, pierwszy priorytet z wytycznych, zrodla oficjalne i niezalezne analizy otrzymuja osobna pule wynikow. W podgladzie widac date publikacji, trafnosc i zapytanie dla kazdego zrodla. Po napisaniu tekstu osobny fact-check usuwa niepotwierdzone premiery, wersje modeli, daty i liczby. Audyt z krytyczna luka albo linkiem spoza researchu zatrzymuje zapis. Oficjalny obraz z RSS moze trafic na okladke, a najwazniejsze punkty do bloku W skrocie na stronie. Brak dzialajacych zrodel lub niespelnienie minimalnej liczby materialow, zrodel oficjalnych i domen przerywa generowanie przed utworzeniem i publikacja artykulu. Tryb bez researchu trzeba wybrac swiadomie i jest przeznaczony do tresci evergreen, nie do biezacych newsow.

Usuniecie artykulu w Mumro nie usuwa wpisu ze strony.

Artykul jest tylko archiwizowany lokalnie. Zdalny wpis trzeba usunac bezposrednio w WordPressie albo wlasnym CMS.

Statusy i problemy

Statusy lokalne to draft, scheduled, published, failed i archived. Przy statusie failed sprawdz komunikat bledu przy artykule, popraw konfiguracje lub dane i ponow publikacje. Po awarii sieci sprawdz rowniez strone docelowa, bo CMS mogl zapisac wpis mimo utraty odpowiedzi.

Dla dewelopera

Technologia i architektura

System sklada sie z API, dwoch aplikacji webowych, procesow asynchronicznych i osobnej statycznej dokumentacji.

Backend FastAPI + SQLAlchemy

Python 3.11, Pydantic, Alembic i PostgreSQL.

Panel Mumro React + TypeScript

Vite, TanStack Query, Tailwind, Zod i Recharts.

Praca w tle Celery + Redis

Publikacje, synchronizacja oraz zadania okresowe.

Media S3-compatible storage

Pliki trafiaja do magazynu obiektowego, np. S3 lub MinIO.

Przeplyw zadania

  1. SPA wysyla zadanie do API z kontekstem organizacji.
  2. API sprawdza role, waliduje dane i zapisuje stan.
  3. Celery wykonuje publikacje lub synchronizacje w tle.
  4. Wynik wraca do bazy i jest prezentowany w panelu.

Podzial repozytoriow

  • mumro - API, worker i glowna aplikacja.
  • mumro-admin - panel administracyjny.
  • docs.mumro.io - dokumentacja produktu i API.
WarstwaOdpowiedzialnoscGlowna zasada
API Autoryzacja, walidacja i operacje domenowe. Kazde zapytanie musi respektowac organizacje i role.
Baza danych Stan publikacji, kont, komentarzy i analityki. Migracje Alembic sa jedynym zrodlem zmian schematu.
Worker Operacje zewnetrzne i dlugotrwale. Zadania powinny byc odporne na ponowienie.
Frontend Obsluga procesu uzytkownika i prezentacja stanu. Komunikaty musza pokazywac bledy czesciowe i ograniczenia.
Integracje Platformy spolecznosciowe, storage i obserwowalnosc. Tokeny i sekrety nie moga trafiac do logow ani klienta.
Dokumentacja techniczna

Rozszerzony opis znajduje sie w docs/technical-overview.md. Kontrakt integracyjny i przyklady zapytan sa opisane ponizej w sekcjach API.

Callback Meta zapisuje poprawny wynik atomowo, odrzuca wielokrotny wybor profili, a backend i baza wymuszaja jeden Instagram oraz jeden Facebook na przestrzen. Reconnect aktualizuje wylacznie ten sam identyfikator profilu.

Dla wlasciciela i administratora

Wdrozenie i bezpieczenstwo

Mumro powinno przechodzic etapami od lokalnego developmentu, przez prywatny VPS i zamknieta bete, do publicznej uslugi.

Etap 1 Local

Dane testowe, mocki i szybkie testy modulow.

Etap 2 Prywatny VPS

Ograniczone moduly, HTTPS, backup i jedna zaufana osoba.

Etap 3 Zamknieta beta

Zaproszeni uzytkownicy, monitoring i aktywny support.

Etap 4 Publiczna usluga

Billing, retencja, zgodnosc prawna i testy obciazenia.

Produkcja musi wymuszac

  • HTTPS dla aplikacji, API i panelu admina.
  • Jawne originy CORS bez wildcard.
  • Stale klucze JWT, sekret OAuth state i rate limiting.
  • Backup bazy i storage wraz z testem odtworzenia.

Przed prawdziwym OAuth

  • Zweryfikuj tenant ownership konta i callbacku.
  • Szyfruj tokeny providerow w spoczynku.
  • Uzyj oddzielnych aplikacji i kont sandboxowych.
  • Nie wysylaj mediow do publicznych serwisow tymczasowych.

Na poczatkowym VPS

  • API, PostgreSQL, Redis, harmonogram i lekkie workery.
  • Kontrolowane wywolania publikacji do social media.
  • Tylko ograniczony i automatycznie czyszczony dysk roboczy.

Poza VPS

  • Prywatny object storage dla rosnacych mediow.
  • Szyfrowany, niezalezny backup off-site.
  • Izolowany compute dla ciezkich zadan CPU i GPU.
Pelna lista kontrolna

Rozszerzony opis bramek znajduje sie w docs/deployment-and-security.md. Sam poprawny start kontenerow nie oznacza gotowosci do publicznego udostepnienia.

Dla agentow i deweloperow

Publikowanie artykulow przez API

Klucz smm_... pobierz w aplikacji z Settings -> API keys. Klucz jest przypisany do organizacji, dlatego nie wymaga X-Organization-Id. Operacje zapisu i publikacji wymagaja roli member+.

Zalecany przeplyw

1

Pobierz site_id

GET /api/website-analytics/sites zawsze zwraca tablice; wybierz poprawna domene.

2

Utworz szkic

POST /api/website-articles z unikalnym Idempotency-Key.

3

Utworz grafike

POST /api/website-articles/{id}/visuals tworzy okladke lub karuzele 4:5 albo 1:1.

4

Opublikuj jawnie

POST /api/website-articles/{id}/publish i sprawdz status w body.

Organizacja jest workspace/tenantem API, a site_id identyfikuje nalezaca do niej strone WWW. Nie jest to identyfikator workspace.

Konfiguracja strony i CMS przez API

Zwykle konfiguracje wykonuje uzytkownik w UI. Agent moze jednak dodac strone przez POST /api/website-analytics/sites, zapisac integracje przez PUT /api/website-analytics/sites/{site_id}/cms i sprawdzic ja przez POST /api/website-analytics/sites/{site_id}/cms/test.

Konfiguracja WordPress
{
  "cms_type": "wordpress",
  "cms_endpoint_url": "https://example.com",
  "cms_username": "mumro-publisher",
  "cms_secret": "WORDPRESS_APPLICATION_PASSWORD"
}
Konfiguracja wlasnego CMS
{
  "cms_type": "custom",
  "cms_endpoint_url": "https://example.com/api/mumro/articles",
  "cms_secret": "LONG_RANDOM_SHARED_BEARER_TOKEN"
}

API nie zwraca zapisanego sekretu; pokazuje tylko cms_has_secret. Pominiecie cms_secret przy aktualizacji zachowuje obecny sekret, a clear_secret=true go usuwa.

1. Lista polaczonych stron
curl https://app.mumro.io/api/website-analytics/sites \
  -H "Authorization: Bearer smm_REPLACE_ME"
2. Utworzenie lokalnego szkicu
curl -X POST https://app.mumro.io/api/website-articles \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "site_id": 12,
    "title": "Artykul utworzony przez API",
    "slug": "artykul-utworzony-przez-api",
    "excerpt": "Krotki opis",
    "content_html": "<h2>Wprowadzenie</h2><p>Tresc artykulu.</p>",
    "metadata_json": {
      "source": "customer-crm",
      "source_record_id": "article-123"
    }
  }'
3. Grafika podsumowujaca i karuzela
curl -X POST https://app.mumro.io/api/website-articles/123/visuals \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: article-123-visual-v1" \
  -d '{
    "visual_style": "editorial",
    "cover_mode": "template",
    "visual_format": "square",
    "content_density": "detailed",
    "brand_label": "Mumro",
    "carousel_enabled": true,
    "slide_count": 6,
    "include_sources_slide": true,
    "use_as_featured_image": true
  }'

Wynik ma format 1080 x 1350 px albo 1080 x 1080 px (zalezne od visual_format) i wraca w polu visual_bundle artykulu. Uporzadkowane carousel_asset_ids mozna od razu wykorzystac przy publikacji social media z image_mode="carousel". Tryb template nie zuzywa kredytow obrazu; cover_mode="ai" wymaga gotowego generatora obrazow i rozlicza image.generate.

4. Publikacja aktualnej wersji
curl -X POST https://app.mumro.io/api/website-articles/123/publish \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{"remote_status":"publish"}'
Ten sam pakiet w UI, CMS i social media.

W module Artykuly WWW sekcja Pakiet wizualny pozwala ustawic styl, tlo szablonowe, AI albo zrodlo, format 4:5/1:1, ilosc tresci, etykiete marki, liczbe slajdow i slajd zrodel. Podglad pojawia sie od razu po wygenerowaniu. Te same ustawienia mozna zapisac w harmonogramie Autopilota artykulow. Przycisk zapisu i lista harmonogramow pokazuja, czy wybrano szkic, czy publikacje. Aktywny nowy harmonogram zleca pierwszy przebieg natychmiast; awaryjny sweep podejmuje go w ciagu pieciu minut, jezeli broker byl chwilowo niedostepny. Mozna tez wybrac date i godzine pierwszego startu, zobaczyc piec kolejnych terminow oraz uruchomic dodatkowy przebieg teraz bez przesuwania cyklu. Bledy 401/403/404/422/429 zatrzymuja operacje; tlo AI moze dodatkowo zwrocic 402 lub 502.

Sprawdzaj body odpowiedzi publikacji, nie tylko HTTP.

Awaria zewnetrznego CMS moze zostac zapisana jako HTTP 200 z status="failed" i niepustym last_publish_error. Sukces oznacza oczekiwany status draft, scheduled albo published oraz last_publish_error=null.

Tworzenie artykulu - pola

PoleWymaganeZnaczenie
site_idTakId polaczonej strony.
titleTakTytul, 1-180 znakow.
slugNieMaks. 220 znakow; pusty jest generowany z tytulu.
excerptNieZajawka, maks. 1000 znakow.
content_htmlNieHTML artykulu, maks. 200 000 znakow.
scheduled_atNieData ISO-8601 uzywana przy statusie future.
metadata_jsonNieMetadane integracji; trafiaja do wlasnego CMS.

Tryby publikacji

remote_statusRezultat
draftWysyla lub aktualizuje zdalny szkic.
publishPublikuje od razu.
futureWymaga przyszlego scheduled_at.

Idempotencja tworzenia

Dla jednego logicznego utworzenia zawsze ponawiaj ten sam Idempotency-Key. Pierwszy request zwraca 201, identyczna powtorka 200 i ten sam artykul, a ten sam klucz z innym payloadem zwraca 422 idempotency_key_conflict. Nowy artykul musi dostac nowy klucz.

Wlasny endpoint CMS

Mumro testuje endpoint przez GET z Bearer tokenem. Przy publikacji wysyla POST z naglowkami X-Mumro-Article-Id i X-Mumro-Site-Id oraz obiektem article i site.

Payload wysylany do wlasnego CMS
{
  "article": {
    "id": 123,
    "external_id": null,
    "title": "Tytul",
    "slug": "tytul",
    "excerpt": "Zajawka",
    "content_html": "<p>Tresc</p>",
    "status": "publish",
    "scheduled_at": null,
    "metadata": { "source_record_id": "article-123" }
  },
  "site": {
    "id": 12,
    "name": "Strona klienta",
    "site_url": "https://example.com",
    "domain": "example.com"
  }
}

Endpoint powinien dzialac jako upsert: najpierw po article.external_id, a gdy go nie ma, po stabilnej parze site.id + article.id. To zabezpiecza przed duplikatami po utracie odpowiedzi sieciowej.

Zalecana odpowiedz wlasnego CMS
{
  "external_id": "post-456",
  "external_url": "https://example.com/blog/tytul",
  "status": "published"
}
Bezpieczenstwo wlasnej integracji

Uzywaj HTTPS, dlugiego losowego Bearer tokenu, porownania constant-time, limitu rozmiaru requestu, walidacji body i sanitizacji HTML. Nigdy nie loguj tokenu.

Pierwszy request

Quick start

API akceptuje token Bearer. Najprostszy przeplyw to wygenerowanie klucza API w aplikacji, wybranie przykladu pasujacego do procesu i wyslanie requestu z naglowkiem autoryzacji. Artykul zawsze najpierw powstaje jako lokalny szkic, a publikacja jest osobnym requestem.

1

Wygeneruj klucz

W aplikacji przejdz do Settings -> API keys i utworz nowy klucz smm_....

2

Dobierz przeplyw

Skorzystaj z sekcji Przyklady: artykul WWW, post, reel, story, film albo kolejka.

3

Wyslij request

Dodaj Authorization, a dla tworzenia publikacji takze Idempotency-Key.

Nigdy nie commituj klucza API.

Trzymaj klucz w menedzerze sekretow lub zmiennej srodowiskowej. Jesli klucz wycieknie, odwolaj go i wygeneruj nowy. Klucz wklejony do rozmowy, ticketu albo logu traktuj jako ujawniony; nie zapisuj go w raporcie z testu.

Authentication

Autoryzacja

API przyjmuje token Bearer: klucz API smm_... wygenerowany w UI albo JWT z sesji SPA. Klucze API sa przypisane do organizacji, dlatego naglowek X-Organization-Id jest dla nich opcjonalny. Nowy klucz dziedziczy aktualna role organizacyjna osoby, ktora go utworzyla.

Uzycie klucza

Request header
Authorization: Bearer smm_REPLACE_ME

Klucz jest widoczny tylko raz przy tworzeniu. Jesli go utracisz, odwolaj stary klucz i wygeneruj nowy.

Kiedy wysylac X-Organization-Id

Principal Naglowek wymagany?
API key smm_... Nie, klucze sa org-scoped.
JWT, uzytkownik jednej organizacji Nie, organizacja jest wywnioskowana.
JWT, uzytkownik z co najmniej 2 aktywnymi czlonkostwami Tak, ustaw X-Organization-Id.

Brak naglowka dla multi-org JWT zwraca 401 organization_required.

Odczyt stron i artykulow wymaga roli viewer+. Tworzenie, edycja, archiwizacja i publikacja artykulow wymaga member+.

Idempotency

Idempotencja

Aby bezpiecznie ponawiac requesty po awariach sieci, dolacz naglowek Idempotency-Key. Wartoscia moze byc UUID v4 albo string o dlugosci 16-128 znakow. Okno idempotencji trwa 24 godziny od pierwszego sukcesu, a serwer odsyla wartosc w Idempotency-Key-Echo.

Idempotency header
Idempotency-Key: f47ac10b-58cc-4372-a567-0e02b2c3d479
Sytuacja Odpowiedz
Identyczny payload w ciagu 24 godzin 200 z cache'owanym body pierwszego sukcesu.
Inny request z tym samym kluczem jest nadal przetwarzany 409 z error_code: idempotency_in_progress.
Ten sam klucz, inny payload 422 z error_code: idempotency_key_conflict.
Niepoprawny format klucza 400 z error_code: idempotency_key_invalid.
Wyjatek dla tworzenia artykulow WWW

POST /api/website-articles przechowuje klucz razem z artykulem. Pierwszy request zwraca 201, identyczna powtorka 200, a ten sam klucz z innym payloadem 422 idempotency_key_conflict. Klucz pozostaje przypisany do tego artykulu i nie wygasa po ogolnym 24-godzinnym oknie publikacji social media.

Rate limits

Limity

Limity sa naliczane per klucz API albo per JWT subject z uzyciem sliding window. Udane odpowiedzi zawieraja naglowki X-RateLimit-Limit, X-RateLimit-Remaining i X-RateLimit-Reset. Po przekroczeniu budzetu API zwraca 429 z error_code: rate_limited oraz Retry-After.

60 / 60s POST /api/publications
30 / 60s POST /api/uploads*
300 / 60s Inne /api/*
Przykladowe response headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1718524800
Retry-After: 17

Errors

Bledy

Kazda odpowiedz >= 400 zwraca kanoniczna koperte. request_id pochodzi z naglowka X-Request-Id, a lista error_code jest zamknieta i zdefiniowana w app.services._errors.ERROR_CODES.

ErrorEnvelope
{
  "error_code": "validation_error",
  "error_message": "Walidacja zadania nie powiodla sie",
  "request_id": "1a2b3c...",
  "details": null
}
error_code HTTP Opis
missing_bearer_token401Brak naglowka Authorization albo cookie.
invalid_api_key401Klucz API jest odwolany albo nieznany.
organization_required401Multi-org JWT musi ustawic X-Organization-Id.
organization_forbidden403Principal nie nalezy do wybranej organizacji.
tenant_forbidden403Operacja wymaga wyzszej roli OrgRole.
validation_error422Walidacja body albo query w Pydantic nie powiodla sie.
idempotency_in_progress409Ten sam Idempotency-Key jest nadal przetwarzany.
idempotency_key_conflict422Klucz idempotencji zostal uzyty z innym payloadem.
idempotency_key_invalid400Niepoprawny format Idempotency-Key.
target_not_found404Jeden z targetow nie nalezy do tenanta.
api_route_not_found404Nieznana trasa /api/*; odpowiedz jest JSON-em, nigdy HTML-em SPA.
all_targets_failed422Wszystkie targety publikacji zakonczyly sie bledem.
platform_does_not_support_type422Platforma konta nie obsluguje danego publication_type.
schedule_required_for_custom422schedule_mode='custom' wymaga terminu publikacji.
invalid_schedule_update422Patch harmonogramu laczy niezgodne pola, np. schedule_source='auto' z scheduled_at.
invalid_status_transition409Cancel albo retry zostal wywolany dla niezgodnego statusu joba.
first_comment_retry_unavailable409Brak danych posta lub providera potrzebnych do ponowienia pierwszego komentarza.
scheduled_at_in_past400PATCH scheduled_at wskazuje przeszlosc.
media_too_large413Upload przekracza limit rozmiaru dla typu mediow.
rate_limited429Przekroczono limit per klucz.
account_not_found404account_id nie nalezy do wybranego tenanta.
website_analytics_site_not_found404site_id nie nalezy do wybranego tenanta.
website_article_not_found404Artykul nie istnieje, jest zarchiwizowany albo nalezy do innej organizacji.
website_cms_invalid_config422Konfiguracja CMS jest niekompletna albo niepoprawna.
website_cms_not_configured422Proba publikacji bez skonfigurowanego CMS.
website_article_invalid_state422Niepoprawny stan publikacji, np. brak przyszlej daty.
Blad zdalnego CMS moze przyjsc jako HTTP 200.

Dla endpointu publikacji artykulu zawsze sprawdzaj pola status i last_publish_error. status="failed" oznacza nieudana publikacje.

Przeglad

Mozliwosci API

Jeden klucz smm_... obejmuje caly tenantowy interfejs: publikacje, generatory AI, analitykę, integracje i narzedzia tekstowe. Ponizej skrocony przeglad obszarow. Pelny katalog z polami i statusami znajduje sie w docs/api-reference.md, a maszynowy kontrakt w https://app.mumro.io/openapi.json.

Publikacje i kolejka

Jedna publikacja rozbijana na wiele kanalow, harmonogram, kolejka i ponawianie.

  • POST /api/publications
  • GET /api/publish-jobs

Generatory AI

AI

Posty, rolki, shorty i artykuly z researchu. Generacja rozliczana w kredytach.

  • POST /api/post-generator/generate
  • POST /api/reels/jobs · /api/shorts/jobs

Analityka i insighty

Nowe

Najlepsze godziny i hashtagi, kandydaci do recyklingu oraz zaangazowanie per kanal — z wlasnych danych.

  • GET /api/analytics/posting-suggestions
  • GET /api/analytics/hashtag-suggestions
  • GET /api/analytics/recycling-candidates
  • GET /api/analytics/channel-engagement
  • GET /api/analytics/report

Webhooki wychodzace

Nowe

Podpisane (HMAC-SHA256) zdarzenia do Twoich systemow: publikacje, leady, artykuly.

  • GET/POST /api/webhooks
  • POST /api/webhooks/{id}/test

Profil glosu marki

Nowe

Wspolny ton, fakty i slowa kluczowe wstrzykiwane do generatorow postow, artykulow, chatbota i AI komentarzy. Bez kosztu.

  • GET/PUT /api/brand-voice

Kampanie i UTM

Nowe

Szablony parametrow UTM per przestrzen i tagowanie linkow przed publikacja.

  • GET/PUT /api/campaigns/settings
  • POST /api/campaigns/tag-url

Link-w-bio

Nowe

Hostowana mini-strona z linkami i CTA pod profil social. Bezpieczne linki (tylko http/https) i gotowy URL.

  • GET/PUT /api/link-in-bio/page
  • GET /api/link-in-bio/p/{key}

Sciana opinii

Nowe

Kuratoruj pozytywne komentarze i osadz publiczna sciane opinii jednym skryptem. Pokazywane tylko zatwierdzone.

  • GET/POST /api/testimonials
  • GET /api/testimonials/public/{key}

Wspolna skrzynka

Nowe

Komentarze z social mediow i rozmowy chatbota w jednym, posortowanym strumieniu do obslugi.

  • GET /api/inbox

Komentarze i szablony

Nowe

Wspolna obsluga komentarzy z AI plus wielokrotnego uzytku gotowe odpowiedzi.

  • GET/POST /api/comments…
  • GET/POST /api/reply-templates
Co jest darmowe, a co rozliczane

Konfiguracja i operacje bez generowania, takie jak insighty, profil glosu, UTM, szablony i webhooki, sa darmowe. Kredyty zuzywa praca modeli AI: generowanie i tlumaczenie tekstu, obrazy, lektor oraz render wideo. Autopilot pokazuje laczny szacunek przed zapisem; aktualne ceny i saldo sprawdzisz przez GET /api/usage/prices oraz GET /api/usage/balance.

Reference

Endpointy

Wszystkie endpointy wymagaja naglowka Authorization: Bearer <token>. Endpointy oznaczone jako idempotent honoruja naglowek Idempotency-Key.

Wszystkie endpointy wymagaja naglowka Authorization: Bearer <token>. Endpointy oznaczone jako idempotent honoruja naglowek Idempotency-Key.

Ponizsza tabela to rdzen publikacji. Pelny katalog calego API (reels, shorts, stories, filmy, autopilot artykulow, CMS WWW, komentarze, analityka, usage) — przygotowany tak, by mogl go uzyc deweloper lub agent AI — znajduje sie w docs/api-reference.md. Maszynowy kontrakt: OpenAPI pod https://app.mumro.io/openapi.json (Swagger: https://app.mumro.io/docs).

Method URL Role Idempotent Opis Statusy
POST /api/publications member+ Tak Tworzy unified publication i rozbija ja na jeden PublishJob per target. Body: PublicationCreate. 200, 201, 207, 401, 403, 404, 409, 422, 429
GET /api/publications/capabilities viewer+ - Macierz platforma x typ, limity caption, limity mediow i opcje story. 200, 401, 403, 429
GET /api/publications/preview-schedule viewer+ - Najwczesniejszy wolny slot dla account_id i content_type; is_trial=true wybiera harmonogram Trial Reel. 200, 401, 403, 404, 429
GET /api/publish-jobs viewer+ - Stronicowana kolejka i historia. Filtry: status[], platform[], account_id[], daty, sort, limit, offset. 200, 400, 401, 403, 429
GET /api/publish-jobs/{id} viewer+ - Pojedyncza projekcja joba PublishJobRead. 200, 401, 403, 404, 429
POST /api/publish-jobs/{id}/cancel member+ - Przenosi queued albo scheduled job do statusu canceled. 200, 401, 403, 404, 409, 429
POST /api/publish-jobs/{id}/retry member+ - Przenosi failed albo canceled job do kolejki. 200, 401, 403, 404, 409, 429
POST /api/publish-jobs/{id}/retry-first-comment member+ - Kolejkuje ponowienie tylko pierwszego komentarza, bez ponownej publikacji posta. 202, 401, 402, 403, 404, 409, 429, 503
PATCH /api/publish-jobs/{id} member+ - Edytuje caption, title albo przelacza queued/scheduled job miedzy harmonogramem konta i data reczna. 200, 400, 401, 403, 404, 409, 422, 429
POST /api/publish-jobs/{id}/move member+ - Przesuwa queued/scheduled job. Body decyduje, czy przeliczyc harmonogram, czy zostawic pozycje poza nim. 200, 400, 401, 403, 404, 409, 422, 429
POST /api/publish-jobs/bulk/cancel member+ - Anuluje do 500 jobow. Body: { ids: number[] }. 200, 401, 403, 422, 429
POST /api/publish-jobs/bulk/retry member+ - Ponawia do 500 jobow. Body: { ids: number[] }. 200, 401, 403, 422, 429
POST /api/uploads/init member+ - Inicjuje presigned upload, single PUT albo multipart. 201, 400, 401, 403, 413, 429
POST /api/uploads/{public_id}/complete member+ - Finalizuje presigned upload i oznacza MediaAsset jako ready. 200, 400, 401, 403, 404, 429
POST /api/uploads/{public_id}/abort member+ - Anuluje upload w toku i oznacza asset jako failed. 200, 401, 403, 404, 429
POST /api/uploads/direct member+ - Server-streamed upload do 100 MB. Obraz zwraca wygasajacy download_url i trwaly public_url. 201, 400, 401, 403, 413, 429
POST /api/uploads/from-url member+ - Server-side fetch i upload z zewnetrznego URL z whitelisty. 200, 401, 403, 422, 429, 502
GET /api/website-analytics/sites viewer+ - Tablica polaczonych stron, ich site_id oraz statusu integracji CMS, takze dla jednego wyniku. 200, 401, 403, 429
POST /api/website-analytics/sites member+ - Dodaje polaczona strone. Body: { name, site_url }. 201, 401, 403, 422, 429
PUT /api/website-analytics/sites/{site_id} member+ - Aktualizuje nazwe, URL lub aktywnosc strony. 200, 401, 403, 404, 422, 429
DELETE /api/website-analytics/sites/{site_id} member+ - Dezaktywuje i archiwizuje polaczona strone. 204, 401, 403, 404, 429
PUT /api/website-analytics/sites/{site_id}/cms member+ - Konfiguruje publikacje do WordPressa albo wlasnego CMS. 200, 401, 403, 404, 422, 429
POST /api/website-analytics/sites/{site_id}/cms/test member+ - Testuje zapisana integracje CMS. 200, 401, 403, 404, 429
GET /api/website-articles viewer+ - Lista szkicow i historii publikacji. Filtry: site_id, status, q, limit, offset. 200, 401, 403, 429
POST /api/website-articles member+ Tak Tworzy lokalny szkic. Identyczna powtorka zwraca istniejacy artykul. 200, 201, 400, 401, 403, 404, 422, 429
GET /api/website-articles/{article_id} viewer+ - Pobiera pojedynczy artykul WWW. 200, 401, 403, 404, 429
PUT /api/website-articles/{article_id} member+ - Aktualizuje lokalny artykul. 200, 401, 403, 404, 422, 429
DELETE /api/website-articles/{article_id} member+ - Archiwizuje artykul lokalnie; nie usuwa wpisu z CMS. 204, 401, 403, 404, 429
POST /api/website-articles/{article_id}/visuals member+ Zalecany Tworzy lub odswieza grafike podsumowujaca 4:5 albo 1:1 i opcjonalna karuzele; moze ustawic wynik jako grafike glowna. 200, 400, 401, 402, 403, 404, 422, 429, 502
POST /api/website-articles/{article_id}/publish member+ - Wysyla artykul do WordPressa lub wlasnego CMS. Blokuje nierozwiazane obrazy z X-Amz-Expires. Nalezy sprawdzic status w body. 200, 401, 403, 404, 422, 429
POST /api/website-articles/{article_id}/social-post member+ Tak Zapisuje promocje jako draft albo kolejkuje ja w trybie now/next_slot/custom; obsluguje grafike artykulu, wygenerowana karuzele, wlasny obraz lub brak. 200, 207, 401, 402, 403, 404, 422, 429
GET /api/api-keys member+ - Lista aktywnych kluczy API dla aktualnej organizacji. 200, 401, 403, 429
POST /api/api-keys member+ - Generuje nowy klucz API. Token plaintext wraca tylko raz. 201, 401, 403, 429
DELETE /api/api-keys/{key_id} member+ - Odwoluje klucz API. 204, 401, 403, 404, 429
GET /api/analytics/posting-suggestions viewer+ - Ranking najlepszych slotow (dzien x godzina) z wlasnej historii. Etykiety pewnosci. 200, 401, 403, 429
GET /api/analytics/hashtag-suggestions viewer+ - Hashtagi wg zaangazowania, podzielone na sprawdzone i eksperymentalne. 200, 401, 403, 429
GET /api/analytics/recycling-candidates viewer+ - Najlepsze starsze posty warte ponownej publikacji (okno wieku, ranking). 200, 401, 403, 429
GET /api/analytics/channel-engagement viewer+ - Zaangazowanie per kanal: posty, interakcje, obserwujacy i wskaznik zaangazowania. 200, 401, 403, 429
GET /api/analytics/report viewer+ - Raport okresowy: totals, kanaly, top posty, najlepsze sloty, hashtagi i highlights. 200, 401, 403, 429
GET /api/webhooks · /event-types member+ / viewer+ - Lista webhookow wychodzacych oraz katalog typow zdarzen. 200, 401, 403, 429
POST /api/webhooks member+ - Rejestruje odbiornik HTTPS. Zdarzenia podpisane HMAC-SHA256 (X-Mumro-Signature). 201, 401, 403, 422, 429
POST /api/webhooks/{id}/test member+ - Wysyla podpisany ping i zwraca wynik dostarczenia. 200, 401, 403, 404, 429
GET /api/brand-voice viewer+ / member+ - Profil glosu marki: odczyt (viewer) i zapis (member). Wstrzykiwany do generatorow AI. 200, 401, 403, 422, 429
GET /api/campaigns/settings viewer+ / member+ - Szablony UTM przestrzeni; POST /api/campaigns/tag-url taguje linki. 200, 401, 403, 422, 429
GET /api/reply-templates viewer+ / member+ - Wielokrotnego uzytku gotowe odpowiedzi dla skrzynki komentarzy. 200, 401, 403, 429
GET /api/inbox viewer+ - Wspolny strumien: komentarze social + rozmowy chatbota, sortowane od najnowszych. 200, 401, 403, 429
GET /api/testimonials · /wall viewer+ / member+ - Kuratorowanie opinii i konfiguracja sciany (CRUD member+, import z komentarza). 200, 201, 401, 403, 404, 422, 429
GET /api/testimonials/public/{key} public - Publiczna (bez auth) sciana opinii: tylko zatwierdzone pozycje, pola wyswietlania. 200, 404
GET /api/link-in-bio/page · /links viewer+ / member+ - Konfiguracja mini-strony i przyciskow (linki tylko http/https). 200, 201, 401, 403, 404, 422, 429
GET /api/link-in-bio/p/{key} public - Hostowana mini-strona (link-w-bio) renderowana po stronie serwera. 200, 404

Schemas

Schematy publikacji

Zrodlem kontraktu jest app.schemas.publication.PublicationCreate. Opcje wspolne przekazuj przez common_content.platform_options, a opcje pojedynczego targetu przez overrides[account_id].platform_options.

PublicationCreate
{
  "publication_type": "post|story|reel|film",
  "targets": ["<account_id>"],
  "common_content": {
    "caption": "Hello world",
    "hashtags": ["smm", "automation"],
    "media_asset_ids": ["<media_asset_id>"],
    "subtitle_asset_id": "<srt_media_asset_id>",
    "subtitle_locale": "pl_PL",
    "first_comment_text": "Prepared first comment for IG/FB post or reel",
    "title": "optional (required for film)",
    "description": "optional",
    "cover": { "kind": "frame_at_seconds", "t": 1.5 },
    "platform_options": {
      "youtube": { "privacy": "unlisted", "tags": ["api"] },
      "tiktok": { "privacy_level": "SELF_ONLY", "disable_comment": true },
      "x": { "content_type": "thread", "thread": ["tweet 1", "tweet 2"] },
      "linkedin": { "content_type": "article", "url": "https://example.com" }
    }
  },
  "overrides": {
    "<account_id>": {
      "caption_override": "...",
      "hashtags_override": ["..."],
      "media_override": ["<media_asset_id>"],
      "story_options": { "link_sticker_url": "https://example.com" },
      "cover_override": { "kind": "asset", "asset_id": 123 },
      "title_override": "...",
      "description_override": "...",
      "subtitle_asset_id": "<srt_media_asset_id>",
      "subtitle_locale": "pl_PL",
      "first_comment_text": "Prepared first comment for this target",
      "tags_override": ["yt", "tags"],
      "share_to_feed": true,
      "fb_title": "Facebook reel title",
      "fb_comment_text": "Legacy Facebook-only first comment alias",
      "is_trial": true,
      "platform_options": { "privacy": "private" },
      "scheduled_at": "2026-07-01T15:00:00+02:00",
      "target_ig": true,
      "target_fb": false
    }
  },
  "schedule_mode": "draft|now|next_slot|custom",
  "scheduled_at": "2026-07-01T15:00:00+02:00",
  "scheduled_at_per_target": {
    "<account_id>": "2026-07-01T15:00:00+02:00"
  }
}

Scheduling contract

Gdy schedule_mode jest pominiete albo ma wartosc next_slot, API uzywa harmonogramu konta i zapisuje job jako schedule_source="auto". custom wymaga scheduled_at i zapisuje manual. now publikuje natychmiastowo poza harmonogramem, tez jako manual. Dla posta draft zapisuje edytowalny szkic bez joba workera.

schedule_modeZnaczenieschedule_source
omitted / next_slotUzyj harmonogramu konta.auto
customUzyj podanej daty publikacji.manual
nowWyslij job do publikacji od razu.manual

GET /api/publish-jobs pokazuje schedule_source. Wartosci auto moga byc przeliczane przez harmonogram. Wartosci manual sa poza harmonogramem i nie sa ruszane przez jego przeliczenia. Gdy auto ma scheduled_at=null, job nadal nalezy do harmonogramu i nie jest publikowany natychmiastowo.

Preview Instagram Trial Reel
GET /api/publications/preview-schedule?account_id=10&content_type=reel&is_trial=true

Gdy is_trial jest pominiete, API uzywa domyslnej wartosci ig_trial_reels konta. Odpowiedz zwraca rozstrzygniete is_trial i tablice warnings. Kod trial_reel_schedule_requires_is_trial oznacza, ze zwykly Reel nie ma slotu, ale konto ma dostepny slot Trial Reel.

Jeden publiczny identyfikator joba

Dla postow, Stories i Reels jobs[].job_id z POST /api/publications jest tym samym numerem co items[].id z listy i parametr {id} tras detail/cancel/retry/move/patch. Dla filmu job_id jest identyfikatorem filmu obslugiwanym przez osobna powierzchnie /api/films/*. media_asset_id jest osobnym identyfikatorem zasobu mediowego.

Automatyczny scheduler jest globalnie dlawiony: jezeli kilka pozycji jest gotowych w tym samym ticku, Mumro wrzuca do publikacji najwyzej jedna i zostawia pozostale na kolejne przebiegi. Scheduler czeka tez, gdy publikacja juz trwa albo kolejka publikacji ma zaleglosc, wiec opozniony harmonogram nie powinien wypchnac wielu postow naraz.

Return job to account schedule
PATCH /api/publish-jobs/123
{
  "schedule_source": "auto"
}
Pin manual date
PATCH /api/publish-jobs/123
{
  "scheduled_at": "2026-07-15T18:00:00+02:00"
}
Move and shift schedule
POST /api/publish-jobs/123/move
{
  "position": 1,
  "schedule_policy": "shift_schedule"
}

schedule_policy="keep_time" zmienia kolejnosc listy, oznacza przesuwany job jako manual i nie zmienia dat innych jobow.

Adapter-facing keys

Platform key Common fields
youtubetitle, description, tags, category / category_id, privacy / privacy_status
tiktokcontent_type, privacy_level, disable_duet, disable_comment, disable_stitch, cover_ms, cover_index
x / twittercontent_type, thread
linkedincontent_type, url, title, visibility
instagram_facebookfb_title, first_comment_text, fb_comment_text, is_trial; subtitle_asset_id / subtitle_locale dla napisow Facebook Reel; uzyj target_ig / target_fb dla fan-out IG vs FB. share_to_feed wraca w capabilities jako unavailable=true i nie jest wykonywane przez adapter publikacji.

Dla targetow Instagram/Facebook pola fb_title, first_comment_text, fb_comment_text i is_trial mozna przekazac bezposrednio w overrides[account_id] albo wewnatrz overrides[account_id].platform_options. Pola bezposrednie wygrywaja, jesli oba warianty sa obecne.

first_comment_text dodaje przygotowany pierwszy komentarz po udanej publikacji posta albo rolki Instagram/Facebook. Mozna go podac w common_content.first_comment_text, overrides[account_id].first_comment_text albo w odpowiednim platform_options. Wyslanie komentarza jest best-effort: jego stan widac jako first_comment_status i first_comment_results. Blad komentarza nie oznacza nieudanej publikacji; mozna ponowic tylko komentarz przez POST /api/publish-jobs/{id}/retry-first-comment. fb_comment_text zostaje jako zgodny wstecz alias tylko dla Facebooka.

Dla obrazow upload zwraca trwaly public_url oraz krotko wazny, podpisany download_url. W HTML artykulu zapisuj tylko public_url; download_url sluzy do natychmiastowego podgladu. Publikacja i planowanie sa blokowane, jesli po normalizacji pozostaje obraz z X-Amz-Expires. Dla grafiki glownej uzyj featured_image_asset_id, featured_image_alt i opcjonalnego featured_image_caption; odpowiedz zawiera trwaly featured_image_url.

Napisy SRT sa natywnymi napisami Meta/Facebook dla wideo. Uploaduj plik .srt jako asset subtitle i przekaz jego numeryczne id jako subtitle_asset_id. Pole jest wykonywane tylko dla powierzchni Facebook Reel (target_fb=true). Instagram Reels Graph API nie przyjmuje plikow SRT; target tylko IG z subtitle_asset_id zostanie odrzucony z media_asset_invalid. subtitle_locale domyslnie ma wartosc pl_PL i musi miec format Meta, np. pl_PL albo en_US.

Zeby uzyc tego samego MP4 na Instagramie i Facebooku, uploaduj plik raz przez POST /api/uploads/direct albo presigned upload i przekaz zwrocone numeryczne id w common_content.media_asset_ids. Nie tworz osobnych uploadow per platforma, chyba ze pliki naprawde sie roznia.

PublicationCreateResponse
{
  "publication_id": "<uuid5 of (organization, idempotency_key)>",
  "request_id": "<X-Request-Id>",
  "jobs": [
    {
      "target_id": "<account_id>",
      "job_id": "<queue_job_id_or_film_job_id | null>",
      "status": "draft|scheduled|queued|succeeded|failed",
      "schedule_source": "auto|manual|null",
      "scheduled_at": "ISO-8601 | null",
      "error_code": "string | null",
      "error_message": "string | null"
    }
  ],
  "summary": { "error_code": "all_targets_failed" }
}

Odpowiedzi JSON deklaruja Content-Type: application/json; charset=utf-8. Nieznana sciezka /api/* zwraca JSON 404 api_route_not_found i nie przechodzi do fallbacku SPA.

Live reference

Capabilities

Aktualna macierz platforma x typ publikacji i limity mediow sa wystawione przez GET /api/publications/capabilities. Poniewaz macierz zmienia sie wraz z platformami i limitami, kanoniczna odpowiedz powinna byc pobierana runtime.

Token sluzy tylko do tego requestu w przegladarce i nie jest zapisywany.

Response shape lub wynik live
{
  "platforms": {
    "instagram_facebook": {
      "supported_types": ["post", "reel", "story"],
      "caption_limits": { "post": 2200, "reel": 2200, "story": 0 },
      "platform_options": {
        "content_type": {
          "type": "enum",
          "values": ["auto", "image", "video"],
          "supported_on_create": true,
          "supported_on_edit": false,
          "legacy_only": false,
          "unavailable": false
        },
        "fb_title": {
          "type": "string",
          "max_length": 255,
          "supported_on_create": true,
          "supported_on_edit": true,
          "legacy_only": false,
          "unavailable": false,
          "accepted_locations": [
            "common_content.platform_options.instagram_facebook.fb_title",
            "overrides.*.platform_options.fb_title",
            "overrides.*.fb_title"
          ]
        },
        "first_comment_text": {
          "type": "string",
          "max_length": 2000,
          "surface": "instagram_facebook_post_reel",
          "supported_on_create": true,
          "supported_on_edit": false,
          "legacy_only": false,
          "unavailable": false,
          "accepted_locations": [
            "common_content.first_comment_text",
            "common_content.platform_options.instagram_facebook.first_comment_text",
            "overrides.*.first_comment_text",
            "overrides.*.platform_options.first_comment_text"
          ],
          "reason": "Posted best-effort after an Instagram/Facebook post or reel is published. Comment failure does not fail the publication."
        },
        "is_trial": {
          "type": "boolean",
          "supported_on_create": true,
          "supported_on_edit": true,
          "legacy_only": false,
          "unavailable": false,
          "accepted_locations": [
            "common_content.platform_options.instagram_facebook.is_trial",
            "overrides.*.platform_options.is_trial",
            "overrides.*.is_trial"
          ]
        },
        "subtitle_asset_id": {
          "type": "integer",
          "asset_type": "subtitle",
          "format": "srt",
          "surface": "facebook_reel",
          "supported_on_create": true,
          "supported_on_edit": false,
          "legacy_only": false,
          "unavailable": false,
          "accepted_locations": [
            "common_content.subtitle_asset_id",
            "overrides.*.subtitle_asset_id"
          ],
          "reason": "Executed only for the Facebook Reel/video surface. Instagram Reels Graph API does not accept SRT caption files."
        },
        "subtitle_locale": {
          "type": "string",
          "default": "pl_PL",
          "format": "meta_locale",
          "surface": "facebook_reel",
          "supported_on_create": true,
          "supported_on_edit": false,
          "legacy_only": false,
          "unavailable": false,
          "accepted_locations": [
            "common_content.subtitle_locale",
            "overrides.*.subtitle_locale"
          ]
        },
        "share_to_feed": {
          "type": "boolean",
          "supported_on_create": false,
          "supported_on_edit": false,
          "legacy_only": false,
          "unavailable": true,
          "reason": "Not currently executed by the Instagram/Facebook publishing adapter."
        }
      }
    }
  },
  "media_limits": {
    "post": { "types": ["image/jpeg", "image/png", "image/webp"], "max_mb": 10, "count_max": 10 },
    "reel": { "types": ["video/mp4", "video/quicktime"], "max_mb": 500, "count_max": 1 }
  },
  "story_options": {
    "instagram_facebook": {
      "link_sticker_url": { "type": "url", "max_length": 2000 }
    }
  }
}

Kazda opcja w platform_options ma metadane wykonania: supported_on_create, supported_on_edit, legacy_only i unavailable. Dla Instagram/Facebook is_trial, fb_title, first_comment_text i fb_comment_text mozna wyslac bezposrednio w overrides[account_id] albo w overrides[account_id].platform_options. first_comment_text mozna tez podac raz w common_content.first_comment_text; komentarz jest dodawany best-effort po udanym poscie albo rolce IG/FB.

Examples

Przyklady integracji

Zastap smm_REPLACE_ME realnym kluczem API. Requesty kieruj do https://app.mumro.io.

Utworz i opublikuj artykul WWW

Najpierw pobierz site_id, potem utworz lokalny szkic z kluczem idempotencji, a publikacje wykonaj osobnym requestem. Po publikacji sprawdz status w body.

cURL - utworzenie szkicu
curl -X POST https://app.mumro.io/api/website-articles \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "site_id": 12,
    "title": "Artykul z API",
    "content_html": "<h2>Wprowadzenie</h2><p>Tresc artykulu.</p>",
    "featured_image_asset_id": 41,
    "featured_image_alt": "Opis grafiki glownej",
    "featured_image_caption": "Opcjonalny podpis",
    "metadata_json": {
      "source": "content-agent",
      "source_record_id": "agent-job-123"
    }
  }'
cURL - publikacja
curl -X POST https://app.mumro.io/api/website-articles/123/publish \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{"remote_status":"publish"}'
Python - kontrola wyniku publikacji
published = requests.post(
    f"https://app.mumro.io/api/website-articles/{article_id}/publish",
    headers={"Authorization": f"Bearer {os.environ['SMM_API_KEY']}"},
    json={"remote_status": "publish"},
    timeout=30,
)
published.raise_for_status()
result = published.json()

if result["status"] == "failed":
    raise RuntimeError(result["last_publish_error"])
if result["status"] != "published":
    raise RuntimeError(f"Unexpected status: {result['status']}")
Windows PowerShell 5.1 - utworzenie artykulu

W Windows PowerShell 5.1 koduj JSON jawnie jako bajty UTF-8 i ustaw timeout. Jesli starszy host nadal zawisa, uzyj curl.exe albo PowerShell 7.

$json = @{
  site_id = 12
  title = "Artykul z polskimi znakami"
  content_html = "<p>Tresc artykulu.</p>"
} | ConvertTo-Json -Depth 20 -Compress
$body = [Text.Encoding]::UTF8.GetBytes($json)

Invoke-RestMethod `
  -Method Post `
  -Uri "https://app.mumro.io/api/website-articles" `
  -Headers @{ Authorization = "Bearer $env:SMM_API_KEY"; "Idempotency-Key" = [guid]::NewGuid().ToString() } `
  -ContentType "application/json; charset=utf-8" `
  -Body $body `
  -TimeoutSec 60
Utworz post
cURL
curl -X POST https://app.mumro.io/api/publications \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: f47ac10b-58cc-4372-a567-0e02b2c3d479" \
  -d '{
    "publication_type": "post",
    "targets": [42, 43],
    "common_content": {
      "caption": "Hello from the API",
      "hashtags": ["smm", "automation"],
      "media_asset_ids": [1234]
    },
    "schedule_mode": "now"
  }'
Python requests
import os, uuid, requests

resp = requests.post(
    "https://app.mumro.io/api/publications",
    headers={
        "Authorization": f"Bearer {os.environ['SMM_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "publication_type": "post",
        "targets": [42, 43],
        "common_content": {
            "caption": "Hello from Python",
            "hashtags": ["smm", "automation"],
            "media_asset_ids": [1234],
        },
        "schedule_mode": "now",
    },
    timeout=30,
)
resp.raise_for_status()
print(resp.json())
Node.js fetch
const idempotencyKey = crypto.randomUUID();
const resp = await fetch("https://app.mumro.io/api/publications", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SMM_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": idempotencyKey,
  },
  body: JSON.stringify({
    publication_type: "post",
    targets: [42, 43],
    common_content: {
      caption: "Hello from Node",
      hashtags: ["smm", "automation"],
      media_asset_ids: [1234],
    },
    schedule_mode: "now",
  }),
});
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
console.log(await resp.json());
Zaplanuj reel na nastepny wolny slot
cURL
curl -X POST https://app.mumro.io/api/publications \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: f47ac10b-58cc-4372-a567-0e02b2c3d479" \
  -d '{
    "publication_type": "reel",
    "targets": [55],
    "common_content": {
      "caption": "Reel for next slot",
      "media_asset_ids": [9001]
    },
    "schedule_mode": "next_slot"
  }'
Jeden upload, Instagram Trial Reel i Facebook Reel

Uploaduj MP4 raz i uzyj numerycznego id z odpowiedzi jako common_content.media_asset_ids[0]. POST /api/uploads/direct jest dla plikow do 100 MB; dla wiekszych wideo uzyj presigned upload.

Upload
curl -X POST https://app.mumro.io/api/uploads/direct \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -F "asset_type=video" \
  -F "file=@role-playing-life-01.mp4;type=video/mp4"
Upload response
{
  "asset_id": "4f4d9f1b-ff4e-4a2e-84db-9e6ec1a7dfc0",
  "id": 9001,
  "file_size_bytes": 48239122,
  "download_url": "https://..."
}

Opcjonalne napisy Facebook Reel uploaduj jako osobny asset subtitle. Uzyj zwroconego numerycznego id tylko w override targetu Facebookowego. Instagram Reels Graph API nie przyjmuje plikow SRT.

Upload SRT
curl -X POST https://app.mumro.io/api/uploads/direct \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -F "asset_type=subtitle" \
  -F "file=@role-playing-life-01.pl_PL.srt;type=application/x-subrip"
SRT upload response
{
  "asset_id": "0ca8f11e-b0fe-44d2-bc1c-3ba3b9f1e9be",
  "id": 9002,
  "file_size_bytes": 2188,
  "download_url": "https://..."
}
Publication
curl -X POST https://app.mumro.io/api/publications \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "publication_type": "reel",
    "targets": [19, 23],
    "common_content": {
      "caption": "Role Playing Life",
      "media_asset_ids": [9001],
      "first_comment_text": "Full story and links in the comments."
    },
    "overrides": {
      "19": {
        "target_ig": true,
        "target_fb": false,
        "is_trial": true
      },
      "23": {
        "target_ig": false,
        "target_fb": true,
        "fb_title": "Role Playing Life",
        "subtitle_asset_id": 9002,
        "subtitle_locale": "pl_PL"
      }
    },
    "schedule_mode": "now"
  }'
Jeden request, wiele platform i natywne opcje
cURL
curl -X POST https://app.mumro.io/api/publications \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "publication_type": "post",
    "targets": [42, 77, 88],
    "common_content": {
      "caption": "Launch update",
      "media_asset_ids": [1234, 1235],
      "platform_options": {
        "x": {
          "content_type": "thread",
          "thread": ["Launch update", "More details in the link"]
        },
        "linkedin": {
          "content_type": "article",
          "url": "https://example.com/launch",
          "title": "Launch update"
        },
        "tiktok": {
          "content_type": "carousel",
          "privacy_level": "SELF_ONLY",
          "disable_comment": false
        }
      }
    },
    "overrides": {
      "77": {
        "caption_override": "LinkedIn-specific copy",
        "platform_options": { "visibility": "PUBLIC" }
      }
    },
    "schedule_mode": "now"
  }'
YouTube film z metadanymi
cURL
curl -X POST https://app.mumro.io/api/publications \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "publication_type": "film",
    "targets": [201],
    "common_content": {
      "title": "API release walkthrough",
      "description": "Long-form release video",
      "media_asset_ids": [555],
      "platform_options": {
        "youtube": {
          "privacy": "unlisted",
          "category": "28",
          "tags": ["mumro", "api", "release"]
        }
      }
    },
    "schedule_mode": "custom",
    "scheduled_at": "2026-07-15T18:00:00+02:00"
  }'
Story z link stickerem
cURL
curl -X POST https://app.mumro.io/api/publications \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{
    "publication_type": "story",
    "targets": [101],
    "common_content": { "media_asset_ids": [7777] },
    "overrides": {
      "101": {
        "story_options": { "link_sticker_url": "https://example.com/landing" }
      }
    },
    "schedule_mode": "now"
  }'
Wylistuj kolejke z filtrami
cURL
curl -G https://app.mumro.io/api/publish-jobs \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  --data-urlencode "status=queued" \
  --data-urlencode "status=scheduled" \
  --data-urlencode "platform=instagram_facebook" \
  --data-urlencode "limit=20" \
  --data-urlencode "offset=0"
Zmien tryb planowania albo przesun job
Wroc do harmonogramu
curl -X PATCH https://app.mumro.io/api/publish-jobs/123 \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{ "schedule_source": "auto" }'
Data reczna
curl -X PATCH https://app.mumro.io/api/publish-jobs/123 \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{ "scheduled_at": "2026-07-15T18:00:00+02:00" }'
Przesun i przelicz plan
curl -X POST https://app.mumro.io/api/publish-jobs/123/move \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{ "position": 1, "schedule_policy": "shift_schedule" }'
Przesun poza planem
curl -X POST https://app.mumro.io/api/publish-jobs/123/move \
  -H "Authorization: Bearer smm_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{ "position": 1, "schedule_policy": "keep_time" }'
Anuluj albo ponow job
Cancel
curl -X POST https://app.mumro.io/api/publish-jobs/123/cancel \
  -H "Authorization: Bearer smm_REPLACE_ME"
Retry
curl -X POST https://app.mumro.io/api/publish-jobs/123/retry \
  -H "Authorization: Bearer smm_REPLACE_ME"