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.

Quickstartcurl
# 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 pathWhat it does
GET /api/v1/meCheck that a key works and see its plan.
GET /api/v1/usagePlan, quota and what is left this period.
GET /api/v1/channelsList your connected channels (their ids go into channelIds).
POST /api/v1/postsSchedule a post to one or more channels, with an optional image.
GET /api/v1/postsList 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/webhooksList 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-Event is the event name.
  • Vane-Delivery is the same id on every retry: de-duplicate on it.
  • Vane-Signature is t=<unix>,v1=<hex>, an HMAC-SHA256 of "<t>.<raw body>" with your whsec_… secret, shown once when you create the webhook.
  • Only public https addresses on port 443 are accepted. Redirects are not followed.
Verify a webhookNode.js
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.