SocioRelay

API and Zapier

Connect SocioRelay to the rest of your business. Send drafts into your app from a shop, a form, a spreadsheet or your own system, and hear when posts are approved, published or fail.

Included in Growth, Pro and Agency, and in the free trial. Create a key in your account: API and webhooks.

Ideas

Zapier and Make

Our own Zapier and Make apps are on their way. Until they're listed, use Webhooks by Zapier or Make's HTTP module with the calls below: "POST a draft" as an action, and a webhook (or "GET events") as a trigger.

Authentication

Send your key in the Authorization header. Every call is over HTTPS; the base address is https://sociorelay.com/api/public/v1.

curl https://sociorelay.com/api/public/v1/me \
  -H "Authorization: Bearer sr_live_..."

Businesses

GET /businesses lists the businesses (apps) you can post to. Agencies have one per client. With one business, you can leave out business_id everywhere.

Send a draft

POST /drafts with JSON. Your app collects it within a few minutes and adds it to Scheduled posts, following that business's approval setting (by default it waits for approval; with two-stage approval it goes to a manager, then the client).

FieldRequiredMeaning
textYesThe post. The app makes each platform's version.
business_idWith more than one businessFrom GET /businesses.
platformsNoAny of linkedin, facebook, instagram, x, threads, bluesky, tiktok, youtube, pinterest, google. Default: the business's usual platforms.
image_urlNoAn https:// image (PNG or JPG). Only send images you have the rights to use.
schedule_atNoWhen to publish, for example 2026-11-02T09:30:00Z. Default: the next free slot.
refNoYour own id. Sending the same ref again returns the first draft, so retries never post twice.
curl -X POST https://sociorelay.com/api/public/v1/drafts \
  -H "Authorization: Bearer sr_live_..." -H "Content-Type: application/json" \
  -d '{"text": "New in: our winter menu, from Monday.", "platforms": ["facebook", "instagram"], "ref": "menu-2026-11"}'

The answer (201) is the draft: {"id": 812, "status": "waiting", ...}. Statuses: waiting (not collected yet), in_app, approved, scheduled, published, failed, rejected, cancelled.

GET /drafts/{id} shows one draft; GET /drafts?status=&business_id=&limit= lists them; DELETE /drafts/{id} cancels one the app hasn't collected yet.

Events

draft.created: A draft was sent through the API

post.in_app: A draft reached the app (waiting for approval or scheduled)

post.approved: A post was approved (by the team or the client)

post.changes_requested: A client asked for changes to a post

post.scheduled: A post was scheduled

post.published: A post was published on a platform

post.failed: A post failed to publish

blog.published: A blog article went live

alert: An alert from the app (login expiring, platform not connected, post late)

GET /events?type=post.published&after_id=&limit= lists events, newest first (kept 30 days). Use it for polling triggers.

Webhooks

Add one in your account, or with POST /webhooks {"url": "https://...", "events": ["post.published"]} (answer includes a secret, shown once). DELETE /webhooks/{id} removes it. We POST each event as JSON:

{"id": 5531, "type": "post.published", "created_at": "2026-11-02T09:30:12Z",
 "business": {"id": 41, "name": "Corner Cafe"},
 "data": {"post_id": 207, "platform": "instagram", "url": "https://www.instagram.com/p/...", "draft_id": 812}}

Every request has a SocioRelay-Signature header: t=<unix time>,v1=<signature>, where the signature is the hex HMAC-SHA256 of <t>.<raw body> with your secret. Check it, and reject times more than 5 minutes old:

// PHP
parse_str(str_replace(",", "&", $_SERVER["HTTP_SOCIORELAY_SIGNATURE"]), $sig);
$body = file_get_contents("php://input");
$ok = hash_equals(hash_hmac("sha256", $sig["t"] . "." . $body, $secret), $sig["v1"]) && abs(time() - (int)$sig["t"]) < 300;
# Python
import hmac, hashlib, time
t, v1 = [p.split("=", 1)[1] for p in request.headers["SocioRelay-Signature"].split(",")]
ok = hmac.compare_digest(hmac.new(secret.encode(), f"{t}.".encode() + request.body, hashlib.sha256).hexdigest(), v1) and abs(time.time() - int(t)) < 300

Answer with any 2xx within 15 seconds. We retry failures after 1 and 5 minutes, then 30 minutes, 2, 6 and 24 hours. Answering 410 Gone switches the webhook off; so do 50 failures in a row.

Limits and errors

Up to 120 requests a minute per key (then 429 with Retry-After). Errors are JSON: {"error": {"type": "invalid_request", "message": "..."}} with 400, 401 (key), 402 (plan), 404, 409, 422 (a field is wrong) or 500.

Content sent through the API is your content: the terms of service (section 7 on AI and automatic posting, section 9 on the API) apply. Questions: info@sociorelay.com.