Developer Docs
A REST API for scripts and CI pipelines. An MCP endpoint for AI assistants — publish from Cursor, VS Code, and Claude Desktop without leaving your editor.
Quick start
Create an account
14-day free trial — no card required. API key access is included.
Generate an API key
Dashboard → API Keys → Create. Keys are prefixed omv_ and shown once.
Configure channels
Add credentials for your target platforms — Bluesky, dev.to, Mastodon, GitHub, etc.
Use the REST API from any HTTP client, CI pipeline, or server-side script.
Base URL: https://api.omnivocal.io/api/v1
All API requests require a Bearer token. Generate keys in the dashboard under API Keys — available during your trial and on the Solo plan. The key is shown only once — store it in your CI secrets.
Authorization: Bearer omv_YOUR_API_KEY
All errors return a JSON body with an error string and a standard HTTP status code.
| Status | Meaning |
|---|---|
| 400 | Bad request — validation error, invalid JSON |
| 401 | Missing or invalid API key |
| 403 | Plan limit reached or action not permitted |
| 404 | Resource not found |
| 413 | Payload too large (asset uploads) |
| 500 | Internal server error |
Publish content to one or more configured channels. Supports immediate publishing, future scheduling via publish_at, and Telegram approval flows.
| Field | Type | Req | Description |
|---|---|---|---|
| content.title | string | ✓ | Post title |
| content.body | string | ✓ | Post body — Markdown by default |
| content.body_format | markdown | html | Default: markdown | |
| content.media_urls | string[] | Image URLs. Max 4. Use upload_asset to host them. | |
| content.tags | string[] | Tags for blog platforms (dev.to max 4) | |
| content.canonical_url | string | Original URL when cross-posting — improves SEO | |
| targets[].channel | string | ✓ | github bluesky devto hashnode mastodon ghost slack discord brevo beehiiv threads telegram |
| targets[].publish_at | ISO 8601 | Schedule for later — omit for immediate | |
| options.require_approval | boolean | Send to Telegram for human approval first |
Example
curl -X POST https://api.omnivocal.io/api/v1/broadcast \
-H "Authorization: Bearer omv_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": {
"title": "Shipping v2.0",
"body": "## What is new\n\nFaster. More reliable.",
"tags": ["release"],
"canonical_url": "https://myblog.com/v2"
},
"targets": [
{ "channel": "bluesky" },
{ "channel": "devto" },
{ "channel": "slack" },
{ "channel": "github" }
]
}' Response — 201
{
"id": "01J...",
"status": "published",
"targets": [
{ "channel": "bluesky", "status": "success", "url": "https://bsky.app/..." },
{ "channel": "devto", "status": "success", "url": "https://dev.to/..." },
{ "channel": "slack", "status": "success" },
{ "channel": "github", "status": "success", "url": "https://github.com/..." }
]
}
Per-channel secrets. Encrypted at rest — secrets are never returned in GET responses.
Supported channels: github bluesky devto hashnode mastodon ghost slack discord brevo beehiiv threads telegram
/api/v1/credentials — list configured channels /api/v1/credentials/:channel — upsert credentials | Channel | Required fields |
|---|---|
| github | token (PAT), default_repo (owner/repo) |
| bluesky | identifier (handle), password (app password) |
| devto | api_key |
| hashnode | access_token, publication_id |
| mastodon | instance_url, access_token |
| ghost | url, admin_api_key |
| slack | webhook_url |
| discord | webhook_url |
| brevo | api_key, list_ids, sender_name, sender_email |
| telegram | bot_token, chat_id and/or publish_chat_id |
curl -X PUT https://api.omnivocal.io/api/v1/credentials/bluesky \
-H "Authorization: Bearer omv_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "identifier": "you.bsky.social", "password": "xxxx-xxxx-xxxx-xxxx" }' /api/v1/credentials/:channel — remove a channel Broadcast records with per-channel delivery statuses.
/api/v1/posts List posts, newest first. Query params: page (default 1), per_page (default 20, max 100).
/api/v1/posts/:id Single post with all target statuses and URLs.
/api/v1/posts/:id Delete a post record. Returns 403 if the post is already published — OmniVocal does not retract from external platforms.
Upload images and video to the OmniVocal CDN (Cloudflare R2). Returns a permanent public URL to use in broadcast as content.media_urls.
| Plan | Images | Video |
|---|---|---|
| Trial / Solo | JPG, PNG, GIF, WebP — max 10 MB | MP4, MOV, WebM — max 100 MB |
| Solo | JPG, PNG, GIF, WebP — max 10 MB | MP4, MOV, WebM — max 100 MB |
multipart/form-data (recommended)
curl -X POST https://api.omnivocal.io/api/v1/assets \ -H "Authorization: Bearer omv_YOUR_API_KEY" \ -F "file=@/path/to/screenshot.png"
Raw body — for large video / streaming
curl -X POST https://api.omnivocal.io/api/v1/assets \ -H "Authorization: Bearer omv_YOUR_API_KEY" \ -H "X-Filename: demo.mp4" \ -H "Content-Type: video/mp4" \ --data-binary @demo.mp4
Response — 201
{"url": "https://api.omnivocal.io/assets/usr_abc/screenshot-1743600000.png"}
OmniVocal exposes a Streamable HTTP MCP endpoint. Add it to your IDE to publish, commit files, and upload assets without leaving your AI assistant.
Endpoint: https://api.omnivocal.io/mcp
The same Bearer token auth applies. See the IDE Setup page in your dashboard for Cursor / VS Code / Claude Desktop config snippets.
The endpoint supports tools/list and tools/call via JSON-RPC 2.0 POST.
list_credentials no parameters Returns the channels you have configured. Always call this first — AI must not assume what channels are available before calling broadcast_post.
broadcast_post Publish content to one or more channels. Supports scheduling and Telegram approval.
| Parameter | Type | Req | Description |
|---|---|---|---|
| content.title | string | ✓ | Post title |
| content.body | string | ✓ | Markdown body. Inline images via  are fine. |
| content.body_format | markdown | html | Default: markdown | |
| content.media_urls | string[] | CDN URLs. Use upload_asset to host them first. | |
| content.tags | string[] | Tags for blog platforms | |
| content.canonical_url | string | Original URL for cross-post SEO | |
| targets[].channel | string | ✓ | From list_credentials output |
| targets[].publish_at | ISO 8601 | Schedule; omit for immediate | |
| options.require_approval | boolean | Route through Telegram first |
github_commit Create or update a file in a GitHub repository using your configured GitHub credentials.
| Parameter | Type | Req | Description |
|---|---|---|---|
| repo | string | ✓ | owner/repo |
| path | string | ✓ | File path, e.g. posts/2026-04-02.md |
| content | string | ✓ | Full file content |
| message | string | Commit message. Auto-generated if omitted. | |
| branch | string | Target branch. Default: main |
upload_asset Upload an image or video to the OmniVocal CDN. Returns a URL to use in broadcast_post as media_urls. Images max 10 MB, video max 100 MB (MP4/MOV/WebM).
| Parameter | Type | Req | Description |
|---|---|---|---|
| filename | string | ✓ | e.g. screenshot.png |
| data | string | ✓ | Base64-encoded file content |
| mime_type | string | ✓ | e.g. image/png, video/mp4 |
14-day free trial — full access from day one. No credit card required.