---
title: "API & MCP docs — schedule social posts from code | Ravenpost"
description: "Drive Ravenpost from a script or an AI assistant: a REST API and an MCP server over the same publishing rules the dashboard uses, across 9 networks. Free on every plan."
url: https://ravenpo.st/docs/
---

Developers

# Post to every network from code

Ravenpost has two programmable surfaces over the same engine the dashboard runs on: a **REST API** at `/v1` and an **MCP server** for AI assistants. Same personal access token, same validation, same 9 networks — no second set of rules to keep in sync, and no separate plan to buy.

[Overview](https://ravenpo.st/docs/)[REST API](https://ravenpo.st/docs/api/)[MCP server](https://ravenpo.st/docs/mcp/)

[

## REST API

19 endpoints for posts, media, analytics and reference data. Anything that speaks HTTP — a cron job, Zapier, Make, n8n.

Read the reference](https://ravenpo.st/docs/api/)[

## MCP server

19 tools that let Claude and other MCP clients draft, schedule and publish for you — with the platform limits enforced server-side.

Connect a client](https://ravenpo.st/docs/mcp/)

## Get a token

Both surfaces authenticate with the same personal access token, created in dashboard **Settings → API tokens**. A token belongs to one user and one workspace: no endpoint takes a workspace id, so a leaked token cannot be pointed at a workspace it was not minted for. We store a SHA-256 hash and a short prefix for display — the token itself is shown once, at creation, and can be revoked at any time.

Check that it works

```
curl https://api.ravenpo.st/v1/me \
  -H "Authorization: Bearer rvp_your_token_here"
```

## Publish your first post

Three calls: find the accounts to publish to, put the media somewhere the platforms can fetch it, then create the post. Media upload is two steps on purpose — the bytes go straight to object storage with a presigned URL, so a 200 MB video never travels through the API.

1\. List the destinations

```
curl https://api.ravenpo.st/v1/accounts -H "Authorization: Bearer $RVP_TOKEN"

# [{ "id": "acc_a1", "platform": "INSTAGRAM", "username": "ravenpost", ... }]
```

2\. Upload an image

```
# a) ask for a presigned PUT
curl -X POST https://api.ravenpo.st/v1/media/uploads \
  -H "Authorization: Bearer $RVP_TOKEN" -H "Content-Type: application/json" \
  -d '{"filename":"launch.jpg","contentType":"image/jpeg"}'

# b) send the bytes straight to storage
curl -X PUT "$UPLOAD_URL" -H "Content-Type: image/jpeg" --data-binary @launch.jpg

# c) register it, and keep the returned id
curl -X POST https://api.ravenpo.st/v1/media \
  -H "Authorization: Bearer $RVP_TOKEN" -H "Content-Type: application/json" \
  -d '{"type":"IMAGE","storageKey":"'"$STORAGE_KEY"'","url":"'"$URL"'","mimeType":"image/jpeg"}'
```

3\. Create the post — one caption, many networks

```
curl -X POST https://api.ravenpo.st/v1/posts \
  -H "Authorization: Bearer $RVP_TOKEN" -H "Content-Type: application/json" \
  -d '{
    "type": "IMAGE",
    "caption": "We shipped it.",
    "captionOverrides": { "TWITTER": "We shipped it 🚀" },
    "mediaIds": ["med_b2"],
    "accountIds": ["acc_a1", "acc_c3"],
    "action": "schedule",
    "scheduledAt": "2026-08-04T09:00:00.000Z"
  }'
```

The response holds one target per account, each with its own status, permalink and error — a fan-out can partly succeed, and the API reports that rather than flattening it to a single result.

## Limits, errors and what not to hardcode

-   **Read `/v1/platforms`** instead of hardcoding caption budgets, media counts or thread caps. It is generated from the same registry the publisher enforces, so it changes when a platform does.
-   **120 requests/minute per IP** on `/v1`; bulk creation and presigned uploads are lower. Over the limit returns `429`.
-   **Errors are standard HTTP** with a JSON body: `400` validation, `401` bad or revoked token, `403` plan or role, `404` not in this workspace.
-   **Absent is not zero.** A missing analytics metric means it was never collected, not that it is 0 — the API omits it rather than inventing a number.

## Machine-readable

The full surface is published as an OpenAPI document generated from the same source as this site, so it cannot describe a different API than the one above: [/docs/openapi.json](https://ravenpo.st/docs/openapi.json). There is also an [llms.txt](https://ravenpo.st/llms.txt) for assistants reading the site itself.

## Questions

- **Is the API included in every plan?:** Yes. The REST API, the MCP server and outgoing webhooks are on every plan including the free one — they are not an add-on. Your plan's limits (connected accounts, posts per month) apply the same way whether a post comes from the dashboard, a script or an agent.
- **How do I authenticate?:** With a personal access token from dashboard Settings → API tokens, sent as a bearer token. A token is tied to one user and one workspace, so no endpoint takes a workspace id and a token can never reach another workspace. We store only a SHA-256 hash and a short display prefix; the token itself is shown once, at creation.
- **Can an AI assistant post on my behalf?:** Yes — that is what the MCP server is for. Connect it to Claude Code, Claude Desktop or any MCP client with the same token and it can draft, schedule and publish through the same services and validation as the dashboard. It cannot generate images or video: the media tools only ingest files you provide.
- **What are the rate limits?:** 120 requests per minute per IP on /v1, with tighter budgets on the expensive routes (bulk creation, presigned uploads). The limit is deliberately below the dashboard's: the expected failure mode for an API is an automation looping without backoff, not a person clicking.
