Inbound webhooks
A Petals webhook URL is a secret address that anything can POST to. Each POST creates a post in your garden. No code, no API keys, no OAuth — the secret is baked into the URL itself.
1. Get your secret URL
Open Settings → Connections and create a webhook URL. It looks like:
https://petals.blog/api/hook/YOUR-SECRET-TOKEN
Treat it like a password — anyone with the URL can post to your garden. Lost it or leaked it? Rotate it; the old URL stops working immediately.
2. What to send
POST JSON or form-encoded data. Every field is optional, but send at least one of title, url, body, or image (an empty payload is rejected). Common aliases are accepted so you rarely have to rename anything:
| Post field | Accepted keys (first match wins) |
|---|---|
| Title | title, subject, name, headline |
| Link | url, link, permalink, href |
| Body | body, content, text, description, message |
| Image | image, image_url, thumbnail, thumb, photo |
| Date | posted_at, date, published, published_at, timestamp, created_at (falls back to now) |
HTML in the body is sanitized through the same allowlist as blog posts. Posting the same url twice updates that post instead of duplicating it.
curl (the one-liner)
curl -X POST https://petals.blog/api/hook/YOUR-SECRET-TOKEN \
-H "Content-Type: application/json" \
-d '{"title":"Hello","url":"https://example.com/post","body":"Posted from curl."}'
Form-encoded works too:
curl -X POST https://petals.blog/api/hook/YOUR-SECRET-TOKEN \
-d title="Hello" -d url="https://example.com/post" -d body="Posted from curl."
Zapier
Add a Webhooks by Zapier → POST action. Set URL to your secret URL, Payload Type to json, and map your trigger's fields into title, url, body, image, posted_at.
IFTTT
Use the Webhooks service as the action (Make a web request). Method POST, Content Type application/json, and a body like
{"title":"{{Title}}","url":"{{EntryUrl}}","body":"{{EntryContent}}"} using your trigger's ingredients.
Make (Integromat)
Add an HTTP → Make a request module. URL = your secret URL, method POST, body type Raw / JSON, and map fields from earlier modules.
n8n
Add an HTTP Request node. Method POST, your secret URL, Body Content Type JSON, and add parameters title, url, body, etc.
Pipedream
Add an HTTP / Send POST Request action (or a few lines in a Node/Python step) pointing at your secret URL with a JSON body built from steps.trigger.event.
GitHub Actions
Post from a workflow step — e.g. announce a release. Store the secret URL as a repo secret (PETALS_WEBHOOK_URL):
- name: Post to Petals
run: |
curl -X POST "$PETALS_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{"title":"${{ github.event.repository.name }} ${{ github.ref_name }}","url":"${{ github.event.release.html_url }}","body":"New release published."}'
env:
PETALS_WEBHOOK_URL: ${{ secrets.PETALS_WEBHOOK_URL }}
Services that emit webhooks natively
Some tools can POST to a URL directly — point them straight at your secret URL. Their payloads differ, so a thin transform (a Zapier/Make/n8n step) gives the cleanest mapping, but many fields line up out of the box:
Strava
Strava's webhook events carry IDs rather than full activities, so route them through Zapier/Make/n8n (or a tiny relay) to fetch the activity, then POST title + url to your Petals URL.
Discourse
Admin → API → Webhooks → New. Set Payload URL to your secret URL, content type application/json, and subscribe to Post or Topic events. Discourse sends title and post fields that map closely.
GitHub
Repo Settings → Webhooks → Add webhook. Payload URL = your secret URL, content type application/json. Push/release events include a name/html_url; a transform step gives the tidiest result.
Trello
Create a webhook via Trello's API pointed at your secret URL to mirror new cards. Trello's model wraps data under action.data, so a transform step that flattens it to title/url works best.
Ready? Create your webhook URL →