skip to content
markus
back

markus API

programmatic access to your campaigns, contacts, conversations, and more.

base URL

https://markusai.dev/api/v1
llms.txtOpenAPI

the markus API uses REST conventions with JSON request and response bodies. all endpoints require authentication via API key.

responses follow a consistent shape: { success: true, data: ... } for success and { success: false, error: { code, message } } for errors.

MCP server

the markus MCP server lets AI agents (Claude Code, Cursor, etc.) manage campaigns, contacts, conversations, messages, and more via the Model Context Protocol.

install

bash
npx -y @jclvsh/markus-mcp

Claude Code

json
{
  "mcpServers": {
    "markus": {
      "command": "npx",
      "args": [
        "-y",
        "@jclvsh/markus-mcp"
      ],
      "env": {
        "MARKUS_API_KEY": "mk_live_YOUR_API_KEY"
      }
    }
  }
}

add to .claude/settings.json

Cursor

json
{
  "mcpServers": {
    "markus": {
      "command": "npx",
      "args": [
        "-y",
        "@jclvsh/markus-mcp"
      ],
      "env": {
        "MARKUS_API_KEY": "mk_live_YOUR_API_KEY"
      }
    }
  }
}

add to .cursor/mcp.json

available tools

65 tools across 14 categories:

categorytoolsdescription
authentication1verify your API key and view its metadata.
API keys3programmatically manage API keys.
campaigns11create and manage outreach campaigns.
contacts8manage contacts and import leads.
conversations5manage conversations across all channels.
messages6manage message approval workflow and sending.
AI5AI-powered content generation and analysis.
discovery4search for and discover new contacts.
analytics5campaign performance metrics and reporting.
billing1view billing plans and subscription information.
channels3manage connected accounts and multi-channel messaging.
notifications4manage user notifications.
webhooks7manage webhook endpoints for receiving real-time event notifications.
agent credits2credit-based payments for AI agents using x402 (USDC on Base) or MPP (Stripe). 1 credit = 1 campaign (30 contacts, 300 messages, 50 AI generations). no subscription required.

recommended scopes

for most AI agent use cases: campaigns:read, campaigns:write, contacts:read, contacts:write, messages:read, messages:write, ai:read, ai:write

llms.txtOpenAPI spec

authentication

all API requests must include your API key in the Authorization header.

header format

http
Authorization: Bearer mk_live_YOUR_API_KEY

example request

bash
curl -X GET "https://markusai.dev/api/v1/campaigns" \
  -H "Authorization: Bearer mk_live_YOUR_API_KEY"

JavaScript

javascript
const response = await fetch("https://markusai.dev/api/v1/campaigns", {
  headers: {
    "Authorization": "Bearer mk_live_YOUR_API_KEY",
    "Content-Type": "application/json",
  },
});

const { success, data } = await response.json();

Python

python
import requests

response = requests.get(
    "https://markusai.dev/api/v1/campaigns",
    headers={"Authorization": "Bearer mk_live_YOUR_API_KEY"},
)

data = response.json()
security: API keys grant full access to your account. keep them secret and never expose them in client-side code. use environment variables instead.

scopes

API keys can be scoped to limit access. use * for full access, or specify individual scopes like campaigns:read.

scopedescription
campaigns:readlist and view campaigns
campaigns:writecreate, update, delete campaigns
contacts:readlist and view contacts
contacts:writecreate, update, delete contacts
conversations:readlist and view conversations
conversations:writecreate and update conversations
messages:readlist pending messages
messages:writeapprove, reject, retry messages
ai:readview AI usage and suggestions
ai:writegenerate AI content and analysis
discovery:readview discovery results
discovery:writerun discovery searches
analytics:readview analytics data
billing:readview billing information
notifications:readview notifications
notifications:writeupdate notifications
channels:readview connected accounts
channels:writemanage channel connections

error responses

authentication errors return HTTP 401 or 403:

json
{
  "success": false,
  "error": {
    "code": "AUTH_001",
    "message": "invalid or missing API key",
    "requestId": "req_abc123"
  }
}

rate limits

API requests are rate-limited per API key. exceeding limits returns HTTP 429.

limits by scope

scopelimitwindowdescription
global (per key)1201 minuteoverall API request limit
burst (per key)201 secondburst request protection
campaigns:write301 minutecampaign mutations
contacts:write601 minutecontact mutations
ai:write201 minuteAI generation requests
discovery:write51 hourdiscovery searches

response headers

rate limit information is included in response headers:

headerdescription
X-RateLimit-Limitmaximum requests allowed in the window
X-RateLimit-Remainingrequests remaining in current window
X-RateLimit-ResetUTC epoch seconds when the window resets
Retry-Afterseconds to wait before retrying (only on 429)

429 response example

json
{
  "success": false,
  "error": {
    "code": "RATE_001",
    "message": "too many requests. please try again in 45 seconds.",
    "requestId": "req_abc123"
  }
}

authentication

verify your API key and view its metadata.

get information about the currently authenticated API key

API keys

programmatically manage API keys.

list all API keys for your account

create a new API key. the raw key is only returned once.

revoke an API key. this action is irreversible.

campaigns

create and manage outreach campaigns.

list all campaigns

create a new campaign

get a specific campaign with full details

update a campaign

soft-delete a campaign (sets status to 'deleted')

list contacts in a campaign

get campaign usage statistics

trigger AI product analysis for a campaign

list target profiles for a campaign

create a target profile for a campaign

delete a target profile

contacts

manage contacts and import leads.

list all contacts

create a single contact

get a specific contact

update a contact

soft-delete a contact (sets deleted_at timestamp)

bulk import contacts (up to 500 per request)

get contact usage for the current billing period

get conversations for a specific contact

conversations

manage conversations across all channels.

list all conversations

get a conversation with details

get messages for a conversation

mark a conversation as read

get engagement metrics across conversations

messages

manage message approval workflow and sending.

list messages pending approval

approve a pending message for sending

reject a pending message

retry a failed message

submit feedback to revise a message with AI

bulk approve or reject messages

AI

AI-powered content generation and analysis.

generate AI content (email subject + body)

generate campaign-wide content strategy

analyze a response for sentiment and suggested actions

get AI generation usage for the current billing period

get AI-suggested responses for a conversation

discovery

search for and discover new contacts.

run a contact discovery search

run discovery search using campaign target profiles

get the status of a discovery job

list available discovery data sources

analytics

campaign performance metrics and reporting.

get overall analytics overview

get analytics for a specific campaign

get performance metrics over time

get average response time metrics

get contact type distribution

billing

view billing plans and subscription information.

get available billing plans and their features

channels

manage connected accounts and multi-channel messaging.

list connected social accounts

check which channels are available for messaging

send a message through a specific channel

notifications

manage user notifications.

list notifications

update a notification (e.g. mark as read)

delete a notification

mark all notifications as read

webhooks

manage webhook endpoints for receiving real-time event notifications.

list all webhook endpoints

create a new webhook endpoint

get a specific webhook endpoint

update a webhook endpoint

delete a webhook endpoint

send a test event to a webhook endpoint

list recent webhook deliveries

agent credits

credit-based payments for AI agents using x402 (USDC on Base) or MPP (Stripe). 1 credit = 1 campaign (30 contacts, 300 messages, 50 AI generations). no subscription required.

check the agent's current credit balance

purchase 5 credits with x402 or MPP payment

webhook events

receive real-time HTTP POST notifications when events happen in your account.

how webhooks work

1. register a webhook endpoint URL via the API or settings page.

2. select which events you want to receive (or subscribe to all with *).

3. when an event occurs, we send an HTTP POST to your endpoint with the event payload.

4. respond with a 2xx status code within 10 seconds.

payload format

all webhook payloads follow this structure:

json
{
  "id": "evt_uuid",
  "type": "campaign.created",
  "created_at": "2024-01-15T10:30:00Z",
  "data": {
    "id": "uuid",
    "name": "Q1 outreach",
    "status": "draft"
  }
}

signature verification

every webhook request includes an X-Webhook-Signature header. verify it using HMAC-SHA256 with your webhook signing secret.

javascript
import crypto from "crypto";

function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
const payload = await request.text();
const signature = request.headers.get("X-Webhook-Signature");

if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
  return new Response("invalid signature", { status: 401 });
}

const event = JSON.parse(payload);
// Process event...

Python verification

python
import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

event types

campaign

eventdescription
campaign.createda new campaign was created
campaign.updateda campaign was updated
campaign.deleteda campaign was soft-deleted

contact

eventdescription
contact.createda new contact was created or imported
contact.updateda contact was updated
contact.deleteda contact was soft-deleted

conversation

eventdescription
conversation.createda new conversation was started
conversation.reply_receiveda reply was received in a conversation

message

eventdescription
message.senta message was sent
message.delivereda message was confirmed delivered
message.openeda message was opened by the recipient
message.bounceda message bounced
message.approveda pending message was approved
message.rejecteda pending message was rejected

discovery

eventdescription
discovery.completeda discovery search completed successfully
discovery.faileda discovery search failed

delivery policy

webhook delivery is attempted once. your endpoint should respond with a 2xx status code within 10 seconds. automatic retries with exponential backoff are coming soon.

error codes

all errors return { success: false, error: { code, message } }

authentication

codeHTTPdescription
AUTH_001401unauthorized — invalid or missing API key
AUTH_002403forbidden — insufficient permissions
AUTH_003401session expired

API keys

codeHTTPdescription
APIKEY_001401invalid or missing API key
APIKEY_002401API key expired
APIKEY_003401API key revoked
APIKEY_004403scope not granted for this operation
APIKEY_005429API key creation limit reached

campaigns

codeHTTPdescription
CAMP_001404campaign not found
CAMP_002500campaign creation failed
CAMP_003500campaign update failed
CAMP_005409campaign already active
CAMP_007400campaign has no contacts
CAMP_008400invalid campaign status transition
CAMP_009429campaign limit reached for billing period

contacts

codeHTTPdescription
CONT_001404contact not found
CONT_002409duplicate contact email
CONT_003400invalid email address
CONT_007500bulk import failed
CONT_009429contact limit reached for billing period

conversations

codeHTTPdescription
CONV_001404conversation not found
CONV_002500conversation update failed
CONV_003500message send failed

messages

codeHTTPdescription
MSG_001500message send failed
MSG_004409message already approved
MSG_005404message not found
MSG_015429message limit reached for billing period

AI

codeHTTPdescription
AI_001503AI service unavailable
AI_002500AI generation failed
AI_003500AI analysis failed
AI_004429AI rate limit exceeded
AI_005400AI content filtered

discovery

codeHTTPdescription
DISC_001500discovery job failed
DISC_002404discovery job not found
DISC_006429discovery rate limited
DISC_007400invalid search query
DISC_008429discovery quota exceeded

webhooks

codeHTTPdescription
HOOK_001400invalid webhook signature
HOOK_003400invalid webhook payload

rate limiting

codeHTTPdescription
RATE_001429too many requests
RATE_002429API rate limit exceeded

server

codeHTTPdescription
SERVER_001500internal server error
SERVER_002400request validation failed
SERVER_003404resource not found
SERVER_004405method not allowed
SERVER_005400invalid input
SERVER_006500database error
SERVER_008504request timeout

© 2026 markus. all rights reserved.

email feedbacktwitter @jclvsh|Dropspacedropspace|privacy policyterms of service