Developers
Headless and API-first.
Everything the dashboard does for posts is one HTTPS request away: list your channels, schedule a post to several of them, check its status, cancel it, and get a signed webhook when it is published or fails.
# 1. Your key is in the dashboard, under API keys export VANE_API_KEY="cpost_test_…" # 2. Find the ids of your channels curl https://vaneapp.dev/api/v1/channels \ -H "Authorization: Bearer $VANE_API_KEY" # 3. Schedule a post (retry-safe) curl -X POST https://vaneapp.dev/api/v1/posts \ -H "Authorization: Bearer $VANE_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: launch-2026-10-20" \ -d '{ "content": "Shipping v2 today", "channelIds": ["<channel-id>"], "scheduledAt": "2026-10-20T09:00:00Z" }' # Answer { "ok": true, "posts": [{ "status": "scheduled", … }] }
Keys
cpost_live_…publishes and counts against your plan.cpost_test_…validates and answers like a live key, but posts nothing and counts nothing.- Video has its own kind,
cvid_…, limited to the video endpoints. - Keys are shown once and stored only as SHA-256 hashes.
Safe retries
Send an Idempotency-Key with POST /posts and a retry never creates a second post: you get the stored answer back with Idempotent-Replayed: true.
Errors you can branch on
Failures are { "ok": false, "error": "…", "code": "…" }. Use code, not the text. Over a limit you get 429 with Retry-After.
Endpoints
Base URL https://vaneapp.dev. Auth: Authorization: Bearer <key>. The full contract, with every field and error, is the OpenAPI spec.
| Method and path | What it does |
|---|---|
GET /api/v1/me | Check that a key works and see its plan. |
GET /api/v1/usage | Plan, quota and what is left this period. |
GET /api/v1/channels | List your connected channels (their ids go into channelIds). |
POST /api/v1/posts | Schedule a post to one or more channels, with an optional image. |
GET /api/v1/posts | List posts. A sent post carries url, the link to it on its network. |
GET /api/v1/posts/{id} | Status of one post. |
DELETE /api/v1/posts/{id} | Cancel a post that has not been sent yet. |
GET · POST /api/v1/webhooks | List and subscribe webhooks (up to 10 per account). |
DELETE /api/v1/webhooks/{id} | Delete a webhook. |
Webhooks
Vane calls your HTTPS address when a post reaches a final state: post.published or post.failed. Every call is signed so you can prove it came from Vane, and failed deliveries are retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours.
Vane-Eventis the event name.Vane-Deliveryis the same id on every retry: de-duplicate on it.Vane-Signatureist=<unix>,v1=<hex>, an HMAC-SHA256 of"<t>.<raw body>"with yourwhsec_…secret, shown once when you create the webhook.- Only public
httpsaddresses on port 443 are accepted. Redirects are not followed.
import { createHmac, timingSafeEqual } from 'node:crypto'; export function verify(secret, header, rawBody) { const p = Object.fromEntries(header.split(',').map((x) => x.split('='))); // reject old calls (replay protection) if (Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false; const want = createHmac('sha256', secret) .update(`${p.t}.${rawBody}`).digest('hex'); const a = Buffer.from(want), b = Buffer.from(p.v1 ?? ''); return a.length === b.length && timingSafeEqual(a, b); }
Quota and rate limits
Each plan includes a number of API posts a month; GET /usage shows what is left. Past it, requests are refused, or charged at the published rate if you switched overage on. Each key also has a per-minute limit.
Built to be protected
Bot detection, per-address and per-key limits, automatic blocking of abusive addresses and signed webhooks. Read how.
Use it from AI and no-code
The same API powers a Custom GPT, Claude (MCP), Make, Zapier and a WordPress plugin. See integrations.