Bijgewerkt op 24 september 2026. Dit stuk beschrijft nu versie 0.2.1 van linkedin-publisher, met de installatie via pipx en drie manieren om hem te laten draaien.
LinkedIn-posts inplannen kan niet via de officiële API. Die kan alleen direct plaatsen, zonder veld voor een tijdstip.
Elke tool die je scheduling verkoopt lost dat op met een timer aan hún kant.
Ik heb die timer bij mij gezet en er een open source tool van gemaakt: linkedin-publisher.
Je schrijft je posts als gewone tekstbestanden in een map. Is een post aan de beurt, dan plaatst de tool hem via de officiële API.
Hieronder staat hoe je hem installeert, koppelt aan LinkedIn en laat draaien.
Waarom de API niet kan inplannen
De Posts API van LinkedIn kent alleen "nu plaatsen". Dat geldt voor iedereen, ook voor Buffer, Hootsuite en Postiz.
Die tools slaan je post op in hun eigen database en roepen de API aan zodra hun timer afloopt. Je betaalt dus voor een wachtrij.
De publicatie zelf is een API-call die jij ook kunt doen.
Mijn posts stonden al in mijn eigen mappen, met een geplande datum erin. De wachtrij bestond dus al. Er zat alleen niets achter dat hem uitvoerde.
Wat linkedin-publisher doet
Elke post is een Markdown-bestand in een map queue/. Bovenaan staat wanneer hij eruit moet.
Na het plaatsen verhuist het bestand naar published/, met de LinkedIn-URL van de post erin.
Drie dingen doet hij voor je die je met de hand makkelijk vergeet:
- Hij zet je tekst om naar iets wat LinkedIn begrijpt. LinkedIn behandelt tekens als haakjes, sterretjes en de
@als opmaakcode. De tool maakt van je Markdown platte tekst en zet waar nodig een escape voor zulke tekens. Een laatste controle weigert alles wat daarna nog onveilig is. - Hij plaatst nooit twee keer hetzelfde. Vlak voor het versturen en na de uitkomst schrijft hij een regel in een lokaal logbestand, allebei voordat het bestand verhuist. Een geplaatste post biedt hij nooit opnieuw aan, ook niet als je het bestand hernoemt. Is het antwoord van LinkedIn onduidelijk, bijvoorbeeld door een time-out, dan probeert hij het niet zelf opnieuw. Hij vraagt je eerst op LinkedIn te kijken.
- Er gaat niets uit zonder dat een mens het besloot. Standaard meldt hij alleen dat een post aan de beurt is. Of je beslist vooraf, door een post op
queuedte zetten.
Wat hij wel en niet kan
| Wel | Niet |
|---|---|
| Tekstposts | Video |
| Eén afbeelding per post, met verplichte alt-tekst | Documenten en pdf-carrousels |
| Posten als jezelf, vanaf je persoonlijke profiel | Meerdere afbeeldingen in één post |
| Markdown in je bestanden | Polls |
| Hashtags | Posten als bedrijfspagina |
| Privé-notities onder de post die nooit meegaan | Inplannen binnen LinkedIn zelf |
Installeren
Je hebt Python 3.11 of nieuwer nodig. Installeer de tool en maak een map voor je posts:
pipx install git+https://github.com/Vinix24/linkedin-publisher
mkdir ~/linkedin && cd ~/linkedin
linkedin-publisher initinit maakt een configuratiebestand (publisher.toml), een lege .env, een .gitignore, een map queue/ met een voorbeeldpost en een lege map published/.
Een bestaand bestand overschrijft hij nooit.
LinkedIn koppelen
Dit is de enige echte horde. Het kost ongeveer een kwartier en je doet het één keer.
Je hebt een LinkedIn-pagina nodig, ook als je alleen vanaf je persoonlijke profiel post. LinkedIn laat je alleen een app maken die bij een pagina hoort.
Je posts gaan gewoon onder je eigen naam uit.
- Maak een LinkedIn-pagina en zorg dat je er beheerder van bent. Een pagina voor je eigen bedrijf is prima.
- Maak een app aan op linkedin.com/developers/apps/new. Koppel hem aan je pagina en upload een logo, dat is verplicht.
- Tabblad Products: voeg Share on LinkedIn en Sign In with LinkedIn using OpenID Connect toe. Allebei self-serve. Je wacht dus niet op LinkedIn.
- Tabblad Settings: verifieer de app. LinkedIn geeft je een link die een paginabeheerder moet goedkeuren. Ben jij dat, open hem dan en keur hem zelf goed.
- Tabblad Auth: voeg bij de toegestane redirect-URL's precies
http://localhost:8765/callbacktoe. - Zet je gegevens in
.env: de client id en het secret uit het tabblad Auth. - Log in:
linkedin-publisher auth
linkedin-publisher status --onlineHet tweede commando vraagt LinkedIn of je token werkt. Het plaatst niets.
Je eerste post
Een post is een Markdown-bestand met een kop erboven:
---
status: queued
slot: 2026-10-01
slot_time: "10:00"
expires: 2026-10-15
---
De tekst van je post.
---
## Notities
Alles onder een regel met drie streepjes is privé en gaat nooit mee.status: queued betekent klaar om te plaatsen. Alles wat nog niet af is, zet je op draft.
Na de expires-datum slaat de tool de post over, omdat hij dan niet meer klopt.
Wil je een afbeelding erbij? Zet dan format: image en een alt_text in de kop. Het beeld zet je naast de post, met dezelfde naam.
Dagelijks gebruik
linkedin-publisher due # wat is aan de beurt, en waarom de rest niet
linkedin-publisher check # proefdraai: tekens, escapes, controle
linkedin-publisher publish # laat zien wat er precies verstuurd zou worden
linkedin-publisher publish --post # plaatst de volgende post die aan de beurt isWas het antwoord van LinkedIn onduidelijk, kijk dan eerst op je profiel. Staat de post er niet, dan plaats je hem alsnog met publish --post --file <pad> --retry. Een post die al geplaatst is, gaat daarmee nooit opnieuw uit.
Per keer gaat er één post uit. Zijn er twee aan de beurt, dan neemt hij de eerste en meldt hij de tweede.
Een post die zijn tijdslot met meer dan anderhalf uur heeft gemist, gaat niet alsnog uit.
Een post over het nieuws van vanochtend hoort 's avonds niet meer te verschijnen.
Een geplande run meldt dat één keer: met een melding op je computer, of met een rode run in GitHub Actions. linkedin-publisher due laat hem altijd zien. Daarna beslis je zelf: een nieuw tijdslot, of uit de wachtrij.
Lees ook: De eerste 3 processen die je moet automatiseren met AI
LinkedIn-posts inplannen: drie plekken waar hij draait
Omdat de API niet kan inplannen, moet er iets draaien op het moment dat een post aan de beurt is. Er zijn drie manieren, elk met een eigen grens.
| Je eigen computer | GitHub Actions | Een server die altijd aan staat | |
|---|---|---|---|
| Opzetten | schedule install | init --github | schedule install --auto |
| Computer mag uit | Nee | Ja | Ja |
| Wie beslist | Jij, op het moment zelf, of vooraf met --auto | Jij, vooraf, met queued | Jij, vooraf, met queued |
| Kosten | Niets | Actions-minuten | De server |
Op je eigen computer kijkt hij elk kwartier of er iets aan de beurt is. Op een Mac via launchd, op Linux via cron. Standaard krijg je alleen een melding.
Met --auto plaatst hij zelf. Dit werkt alleen als je computer aan staat.
In GitHub Actions mag je computer uit. linkedin-publisher init --github zet twee workflows klaar.
De eerste draait elk half uur tussen 06:00 en 22:59 in je eigen tijdzone. De tweede controleert dagelijks je token.
Een post gaat uit bij de eerste run na zijn tijdslot. Meestal is dat binnen een halfuur, soms later als GitHub druk is.
Hier is geen goedkeurknop op het moment van plaatsen. Op GitHub Free, Pro en Team werken verplichte reviewers alleen in publieke repo's.
Een wachtrij met ongeplaatste posts hoort in een privé-repo. Het besluit valt dus op het moment dat je een post op queued zet en pusht.
Voor een privé-repo geeft GitHub Free 2.000 Actions-minuten per maand. De workflow draait ongeveer 1.100 keer per maand.
Zolang een run binnen een minuut blijft, zit je daaronder. Draai je meer workflows in privé-repo's, controleer dan je verbruik onder Settings, Billing.
Op een server werkt elke Linux-machine die altijd aan staat: een kleine server bij Hetzner of DigitalOcean, een virtuele machine bij Google Cloud, AWS of Azure, of een Raspberry Pi thuis. Twee dingen om te weten:
- Inloggen vraagt een browser. Die heeft een server niet. Log daarom in op je eigen computer en kopieer
.enven.linkedin-tokens.jsonnaar de server. - Gebruik op een server altijd
--auto. Een melding bereikt daar niemand.
Serverless-omgevingen zoals Cloud Run jobs of AWS Lambda werken niet zomaar. De tool bewaart zijn wachtrij en logboek op schijf. Die omgevingen beginnen elke keer leeg.
Het inplannen op Linux is gedekt door de tests. Op een echte server heb ik het nog niet gedraaid.
Het token verloopt na ongeveer 60 dagen
De meeste self-serve apps krijgen van LinkedIn geen refresh-token. Het toegangstoken is ongeveer 60 dagen geldig.
Daarna draai je linkedin-publisher auth opnieuw, op je eigen computer.
In de laatste week voor het verlopen waarschuwt een geplande run op je computer één keer per dag. De commando's due en status doen dat ook. In GitHub Actions kleurt de dagelijkse controle rood.
Je komt dus niet op de ochtend dat je wilt posten voor een verrassing te staan.
Werkt het?
Ik heb de tool getoetst op 183 van mijn eigen postbestanden.
De uitvoer was exact gelijk aan die van de publisher waar hij uit is voortgekomen, inclusief 361 tekens die een escape nodig hadden.
Versie 0.2.1 heeft 76 tests, allemaal groen.
Mijn eerste echte post via de tool ging op 24 september 2026 om 10:00:05 uit, volledig automatisch op het ingeplande tijdslot.
Waar dit niet over gaat
Inplannen lost het plaatsen op, niet het erbij zijn.
De eerste dertig tot zestig minuten na een post bepalen wat hij doet. Elke reactie hoort een antwoord te krijgen.
Een post die om tien uur uitgaat terwijl jij in een klantgesprek zit, vangt niemand op.
Daarom meldt de tool standaard alleen dat een post aan de beurt is. Zelf plaatsen doet hij pas als jij daar vooraf voor kiest.
Het is dezelfde afweging als bij de taken die AI in het MKB vandaag al overneemt: het plaatsen automatiseer je, het gesprek erna niet.
Lees ook: Deterministische kwaliteitspoorten: controles die niet van een oordeel afhangen