Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MatthewSabia1/SubPirate-Pro/llms.txt

Use this file to discover all available pages before exploring further.

Campaign Run Workflow

A campaign run represents a single execution of a campaign, which creates multiple posting attempts. The workflow is:
  1. Queue a run via manual trigger or scheduled dispatch
  2. Build attempt plan by pairing accounts × subreddits × content
  3. Execute attempts sequentially, posting to Reddit
  4. Track status of each attempt (posted, failed, skipped)
  5. Calculate shortfall if daily target not met

Run Status Lifecycle

  • queued: Run is scheduled, waiting to execute
  • running: Run is actively posting
  • completed: All attempts succeeded
  • partial: Some attempts succeeded, some failed/skipped
  • failed: All attempts failed
  • canceled: Run was canceled (e.g., subscription lapsed)

GET /api/campaigns/:id/runs

List all runs for a campaign, paginated. Requires Viewer role.

Path Parameters

id
string
required
Campaign UUID

Query Parameters

cursor
string
Pagination cursor from previous response’s next_cursor
limit
number
default:"20"
Number of runs per page (max 50)

Response

items
array
required
Array of campaign run objects
next_cursor
string
Pagination cursor for next page (null if no more results)

Example Request

import { fetchCampaignRuns } from './campaignApi';

const { items: runs, next_cursor } = await fetchCampaignRuns(campaignId);

console.log(`Loaded ${runs.length} runs`);
runs.forEach(run => {
  console.log(`Run ${run.id}: ${run.status} - ${run.attempt_executed}/${run.attempt_target} attempts`);
});
curl -X GET "https://your-api.example.com/api/campaigns/abc-123/runs?limit=10" \
  -H "Authorization: Bearer YOUR_SUPABASE_JWT"

POST /api/campaigns/:id/run

Trigger a manual campaign run. Requires Editor role and an active subscription.

Path Parameters

id
string
required
Campaign UUID

Request Body

No body required. The run is generated based on current campaign configuration.

Response

run
object
required
The created campaign run object (see GET schema)
queued_after_existing_run
boolean
If true, this run was queued behind an in-flight run
attempts_count
number
Number of posting attempts created for this run

Errors

  • 403: Subscription required, or insufficient campaign role
  • 409: No posts are due right now (daily target already met)
  • 422: Campaign is not ready to run (missing content, accounts, or subreddits)

Example Request

import { triggerCampaignRun } from './campaignApi';

try {
  const result = await triggerCampaignRun(campaignId);
  console.log('Run queued:', result.run.id);
  console.log('Attempts:', result.attempts_count);
  
  if (result.queued_after_existing_run) {
    console.log('⚠️ Run will wait for current run to finish');
  }
} catch (error) {
  if (error.message.includes('subscription_required')) {
    console.error('Upgrade required to run campaigns');
  } else if (error.message.includes('nothing_due')) {
    console.log('Daily target already met');
  } else {
    console.error('Failed to trigger run:', error.message);
  }
}
curl -X POST https://your-api.example.com/api/campaigns/abc-123/run \
  -H "Authorization: Bearer YOUR_SUPABASE_JWT" \
  -H "Content-Type: application/json"

Response Example

{
  "run": {
    "id": "run-uuid-here",
    "campaign_id": "abc-123",
    "run_type": "manual",
    "status": "queued",
    "run_date": "2026-03-02",
    "attempt_target": 10,
    "attempt_executed": 0,
    "attempt_failed": 0,
    "attempt_skipped": 0,
    "shortfall": 10,
    "scheduled_for": "2026-03-02T18:30:00Z",
    "triggered_by": "user-uuid",
    "created_at": "2026-03-02T18:30:00Z"
  },
  "queued_after_existing_run": false,
  "attempts_count": 10
}

GET /api/campaigns/:id/runs/:runId

Get detailed information about a specific run, including all posting attempts. Requires Viewer role.

Path Parameters

id
string
required
Campaign UUID
runId
string
required
Run UUID

Response

run
object
required
Campaign run object (see GET /api/campaigns/:id/runs schema)
attempts
array
required
Array of posting attempt objects

Example Request

import { fetchCampaignRun } from './campaignApi';

const { run, attempts } = await fetchCampaignRun(campaignId, runId);

console.log(`Run ${run.id} - Status: ${run.status}`);
console.log(`Attempts: ${attempts.length}`);

const posted = attempts.filter(a => a.status === 'posted');
const failed = attempts.filter(a => a.status === 'failed');
const skipped = attempts.filter(a => a.status === 'skipped' || a.status === 'deduped');

console.log(`✅ Posted: ${posted.length}`);
console.log(`❌ Failed: ${failed.length}`);
console.log(`⏭️ Skipped: ${skipped.length}`);

attempts.forEach(attempt => {
  const username = attempt.reddit_accounts?.username;
  const subreddit = attempt.subreddits?.name;
  console.log(`  ${attempt.status}: u/${username} → r/${subreddit}`);
  
  if (attempt.status === 'posted') {
    console.log(`    🔗 https://reddit.com/comments/${attempt.reddit_post_id}`);
  } else if (attempt.error_message) {
    console.log(`    Error: ${attempt.error_message}`);
  }
});
curl -X GET "https://your-api.example.com/api/campaigns/abc-123/runs/run-uuid" \
  -H "Authorization: Bearer YOUR_SUPABASE_JWT"

POST /api/campaigns/:id/run/preview

Preview what a campaign run would do without actually executing it. Requires Editor role. Useful for:
  • Validating campaign configuration before running
  • Checking daily progress and remaining posts
  • Debugging account health and subreddit availability

Path Parameters

id
string
required
Campaign UUID

Response

preview
object
required

Example Request

import { fetchCampaignRunPreview } from './campaignApi';

try {
  const preview = await fetchCampaignRunPreview(campaignId);
  
  console.log(`📅 Run Date: ${preview.run_date} (${preview.timezone})`);
  console.log(`🎯 Target: ${preview.attempt_target} attempts`);
  console.log(`✅ Posted Today: ${preview.posted_today}`);
  console.log(`⏳ Remaining: ${preview.remaining_today}`);
  
  if (preview.carry_over > 0) {
    console.log(`📦 Carry-Over: ${preview.carry_over} from previous day`);
  }
  
  if (preview.warnings.length > 0) {
    console.warn('⚠️ Warnings:');
    preview.warnings.forEach(w => console.warn(`  - ${w}`));
  }
  
  if (preview.active_content) {
    console.log('📝 Content:', preview.active_content.title);
  }
  
  console.log(`🔄 Pairings: ${preview.pair_count} account × subreddit combos`);
  console.log(`📊 Attempts: ${preview.attempts.length} planned`);
} catch (error) {
  console.error('Preview failed:', error.message);
}
curl -X POST https://your-api.example.com/api/campaigns/abc-123/run/preview \
  -H "Authorization: Bearer YOUR_SUPABASE_JWT" \
  -H "Content-Type: application/json"

Campaign Run Event Log

Each run maintains a detailed event log for debugging and auditing. See Campaign Events for the events API.

Build docs developers (and LLMs) love