PUBLISHING API
A social media publishing API with approvals built in
Growfinch’s REST API lets your own tools create campaigns, add posts to a business’s queue and read results, with each API key limited to the businesses it was made for. Where a business requires approval, campaigns wait for a person; the API cannot approve.
Updated 22 October 2026 · Growfinch
Use it from whatever already makes your content: a render pipeline, a CMS, an internal app or an AI agent. Your tool sends the post; Growfinch checks it against the business’s rules, holds it for approval where the business asks for that, publishes it at its time through each platform’s official API, and tells you how it went.
That matters more as agents write more of what gets published. In Ahrefs’ survey of 301 marketing and SEO professionals, 7% of marketers using AI say more than 75% of the content they publish is pure AI (Ahrefs, Marketers and AI content creation, 30 September 2026). When an agent drafts your posts, the approval belongs on the server, where no prompt can talk its way past it. AI assistants can use the same actions through Growfinch’s MCP server.
Social media publishing API endpoints
Everything you need to schedule social media posts through the API, for each business the key was made for. All paths sit under /api/v1 on growfinch.com. Every request names its business; Growfinch never picks one for you.
| Method | Path | What it does |
|---|---|---|
| GET | /businesses | The businesses this key may act on, with each one’s publishing policy. |
| GET | /connections | A business’s connected accounts: platform, handle, status and token expiry, never a token. |
| POST | /campaigns/validate | A dry run: the checklist, a preview per platform and what would happen. |
| POST | /campaigns | Create a campaign for one business. |
| GET | /campaigns | A business’s campaigns, by status and dates. |
| GET | /campaigns/:id | One campaign with its posts and history. |
| DELETE | /campaigns/:id | Cancel a campaign’s pending posts. |
| GET | /approvals | Items waiting for a person. Reading only: approving happens in the console. |
| POST | /media | Register an image or video by its SHA-256 and get a signed upload address. |
| POST | /media/:id/complete | Confirm the upload arrived and mark the file ready. |
| GET | /media/:id | One file and its status. |
| GET | /posts/metrics | Daily snapshots per post and 7- and 30-day totals for a business. |
| POST | /webhooks | Register an https endpoint for the events you choose. |
| GET | /webhooks | Your webhook endpoints. |
| DELETE | /webhooks/:id | Remove an endpoint. |
| POST | /webhooks/:id/ping | Send a test event and see the status code your endpoint answered. |
| POST | /queues | Create a weekly timetable (a queue) for a business. |
| GET | /queues | A business’s queues. |
| GET | /queues/:id | One queue with its items. |
| PATCH | /queues/:id | Change slots, accounts, approval mode, order, recycling, the daily maximum, pause or expiry. |
| DELETE | /queues/:id | Delete a queue; its waiting items are cancelled. |
| POST | /queues/:id/items | Add content without a time; the reply says when it will land. |
| GET | /queues/:id/items | A queue’s items, by state. |
| PATCH | /queues/:id/items/:itemId | Move an item, skip it, or hold it until a date. |
| POST | /queues/:id/shuffle | Shuffle the items not yet scheduled. |
| GET | /queues/:id/plan | Which item lands in which slot over the next 1 to 60 days. |
A campaign carries one to 40 posts for one business, each with its platform, format, caption, time and media. A queue item is the same without times: the next free slot in the business’s weekly timetable gives it one. Errors come back as JSON with a code, a message and a request id. A minor version of the API may add fields to responses, so ignore the ones your client doesn’t know.
Keys, scopes and businesses
Each key is made for named businesses and carries scopes:
- campaigns:read to read campaigns, queues and their plans, webhook endpoints and post results.
- campaigns:write to create, change and cancel campaigns and queues.
- media:write to register and upload images and videos.
- webhooks:write to register, test and remove webhook endpoints.
No scope lets a key approve. A request for a business outside the key’s list is refused, and the database keeps each business’s data apart with row security, so a key for one client cannot read another’s campaigns. Growfinch stores a hash of each key, not the key, and records every change a key makes in the audit log. A kill switch in Settings stops every external effect at once, whatever a key asks.
Safe retries
Networks fail halfway through requests. Creating a campaign, a queue or a queue item takes an idempotency key, 8 to 128 characters that you choose. Send the same request again with the same key, after a timeout or a crash, and you get the original back marked replayed instead of a duplicate. Files are registered by their SHA-256, so pushing the same file twice gives you the same record.
Validate before you create. The dry run checks what the real call would check, without storing anything:
- whether each post’s account is connected, or needs reconnecting;
- whether the format exists on that platform and the caption fits its limit;
- the checks the business requires before anything is scheduled;
- what would happen: a draft, waiting for approval, or scheduled.
Webhooks
Register an https endpoint, choose up to 20 events (or all of them), and optionally limit it to some of your businesses. The endpoint’s secret is shown once, when you register it.
| Event | When it fires |
|---|---|
| campaign.approval_required | A campaign or queue item is waiting for a person. |
| campaign.scheduled | A person approved a campaign, or a queue landed one in its slot. |
| campaign.cancelled | A campaign was cancelled. |
| post.published | A post went out, with its platform and permalink. |
| post.failed | A post failed, with the error code and message. |
| connection.expired | An account’s connection expired or was revoked and needs reconnecting. |
| exception.created | A failure that needs a person was filed in Approvals. |
| queue.item_scheduled | A queue item landed in a slot. |
| queue.slot_missed | A slot passed with nothing ready: nothing queued, or the item still waiting for approval. |
| queue.running_low | Fewer days of content remain than the queue’s threshold. |
| webhook.ping | The test event the ping endpoint sends. |
Each delivery is signed: a header carries a timestamp and an HMAC-SHA256 of the timestamp and the raw body, keyed with the endpoint’s secret. Check it before you trust the body, and refuse old timestamps. Deliveries are at least once and retried with growing gaps until your endpoint answers with a success, so deduplicate on the event’s id. Growfinch sends post.failed and connection.expired as soon as it knows; the guide to failed scheduled posts covers the usual causes and fixes.
Platforms behind the API
Growfinch publishes through each platform’s official API, with the permissions an account owner grants when connecting it:
- YouTube: Shorts.
- Instagram: Reels and images, for professional accounts.
- X: posts with media and a first reply.
- LinkedIn: next.
Once a day, Growfinch reads each published post’s counters from the platform: views, likes and comments, and shares where the platform gives them, from YouTube, Instagram and X. LinkedIn gives none to this app, so its posts will show “Not provided”. Nothing is estimated: a counter the platform doesn’t report comes back as null.
Read next: how approval works per business and Growfinch for agencies.
Questions
Is there an API to post to Instagram?
Yes. Growfinch posts Reels and images to connected Instagram professional accounts through Instagram’s official API. Your tool sends the campaign to Growfinch, which publishes it at its time, after a person approves it where the business requires that.
Can I post to LinkedIn through the API?
LinkedIn is next: posting as a member is built and waits for Growfinch’s LinkedIn app. Posting as a company Page needs LinkedIn’s Community Management API and is planned.
Does the API publish immediately?
No. It schedules within the business’s rules: each post has a time, or a queue gives it the next free slot. Where the business requires approval, nothing is scheduled until a person approves it in the console.
How are webhooks signed?
Each delivery carries a signature header with a timestamp and an HMAC-SHA256 of the timestamp and the raw body, keyed with the endpoint’s secret. The secret is shown once, when you register the endpoint. Deliveries are at least once, so deduplicate on the event id.
Is there an SDK?
Not a public one yet. Growfinch has a typed TypeScript client built on the same contract as the API; whether to publish it is still open.
How do I get an API key?
Keys come with early access. When your team is onboarded, we make keys for the businesses and scopes you need.