Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt

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

Campaigns define recurring batch execution configurations. Each campaign targets a decision flow and customer segment, with schedule, volume, and file settings. Campaign runs are individual execution instances.
See the Campaigns feature page for UI guidance on creating and managing campaigns.

Base path

/api/v1/runs

List campaigns

GET /api/v1/runs
Returns a paginated list of campaigns with latest run info.

Query parameters

ParameterRequiredTypeDescription
limitNointegerMax results per page. Default 50, max 200.
offsetNointegerRecords to skip. Default 0.

Response 200

{
  "runs": [
    {
      "id": "camp_001",
      "name": "Weekly High-Value Campaign",
      "status": "active",
      "scheduleType": "weekly",
      "scheduleDayOfWeek": 1,
      "scheduleTime": "09:00",
      "scheduleTimezone": "America/New_York",
      "decisionFlowName": "Q1 Cross-Sell",
      "segmentName": "High Value Customers",
      "segmentCustomerCount": 4521,
      "runCount": 3,
      "lastRunAt": "2026-03-15T14:00:00.000Z",
      "latestRun": {
        "id": "run_003",
        "status": "completed",
        "runNumber": 3
      }
    }
  ],
  "total": 5
}

Create campaign

POST /api/v1/runs
Creates a new campaign configuration. Does not trigger execution — use the trigger endpoint to start a run.

Request body

FieldRequiredTypeDescription
decisionFlowIdYesstringDecision flow to execute
segmentIdYesstringCustomer segment to target
nameNostringCampaign name (auto-generated if omitted)
descriptionNostringCampaign purpose and notes
statusNoenumdraft, active, paused, archived. Default: draft
scheduleTypeNoenummanual, daily, weekly, monthly. Default: manual
scheduleDayOfWeekNointeger0=Sun..6=Sat (for weekly)
scheduleDayOfMonthNostring1-28 or last_working_day (for monthly)
scheduleTimeNostringHH:mm format. Default: 09:00
scheduleTimezoneNostringIANA timezone. Default: UTC
scheduleCronNostringCron expression for custom schedules (e.g., 0 9 * * 1). Used when scheduleType does not cover the desired frequency.
volumeConstraintsNoobject{ maxTotalPerRun?, maxPerOffer?, maxPerChannel? }
fileConfigNoobject{ format, columns[], includePersonalization, destination, s3Path? }
channelIdsNostring[]Batch channel IDs to target (empty = all batch channels)

Example request

{
  "decisionFlowId": "df_001",
  "segmentId": "seg_001",
  "name": "Weekly High-Value Campaign",
  "status": "active",
  "scheduleType": "weekly",
  "scheduleDayOfWeek": 1,
  "scheduleTime": "09:00",
  "scheduleTimezone": "America/New_York",
  "volumeConstraints": { "maxTotalPerRun": 10000, "maxPerOffer": 500 },
  "fileConfig": {
    "format": "csv",
    "columns": ["customer_id", "offer_name", "channel", "score"],
    "destination": "download"
  }
}

Response 201

Returns the created campaign object.

Update campaign

PUT /api/v1/runs/:id
Updates campaign configuration. Accepts any combination of the following fields: name, description, status, scheduleType, scheduleDayOfWeek, scheduleDayOfMonth, scheduleTime, scheduleTimezone, scheduleCron, volumeConstraints, fileConfig, channelIds, decisionFlowId, segmentId.
Unlike most update endpoints, PUT allows changing decisionFlowId and segmentId to retarget a campaign to a different decision flow or customer segment.

Delete campaign

DELETE /api/v1/runs/:id
Deletes the campaign and all its runs. Requires admin role.

Get campaign detail

GET /api/v1/runs/:id
Returns the campaign config with the last 10 runs, resolved offer names in summaries, and enriched per-customer results.

Trigger a campaign run

POST /api/v1/runs/:id/campaign-runs
Creates and starts a new campaign run. The run is enqueued for processing by worker pods via BullMQ, with inline fallback when Redis is unavailable.

Response 201

{
  "id": "crun_001",
  "campaignId": "camp_001",
  "runNumber": 4,
  "triggeredBy": "manual",
  "status": "pending",
  "createdAt": "2026-03-22T09:00:00.000Z"
}

List campaign runs

GET /api/v1/runs/:id/campaign-runs
Returns execution history for a campaign, ordered by run number descending (max 50).

Execute a run inline (background)

POST /api/v1/runs/execute-inline
Fire a Run execution in the background and return immediately. The route at src/app/api/v1/runs/execute-inline/route.ts:10-22 calls executeBatchRun(runId, decisionFlowId, segmentViewName, tenantId) from src/lib/batch-executor.ts:58 without awaiting — the response is sent before the batch starts producing output, and any per-run failure is logged via getLogger("runs-execute-inline") rather than returned to the caller. This endpoint is for inline triggers from a single-tenant dev environment or a backup path when the BullMQ worker tier is degraded. Production triggering should use POST /api/v1/runs/:id/campaign-runs so the run gets a CampaignRun row, retry semantics, and DLQ visibility.

Request Body

runId
string
required
Identifier of the Run row that the executor will update with status, startedAt, and completedAt.
decisionFlowId
string
required
Decision flow to execute against.
segmentViewName
string
required
Customer-segment view name. The executor reads from this Postgres view to enumerate target customers.

Response

Returned at route.ts:21. Status 200.
{
  "status": "executing",
  "runId": "run_42"
}
The response is sent the moment the executor is dispatched. The caller monitors progress by polling GET /api/v1/runs/:id.

Status codes

CodeWhen
200Executor dispatched (returned immediately, before completion)
400Missing runId, decisionFlowId, or segmentViewName
401 / 403Caller is not authenticated, or not admin / editor

Roles

admin, editor.
Errors raised by executeBatchRun after the response is sent are logged but never surfaced to the caller. The Run row’s status and error columns are the source of truth for outcome — poll GET /api/v1/runs/:id to see the final state.

Campaign statuses

StatusDescription
draftCreated but not yet active
activeLive — scheduled runs execute automatically
pausedTemporarily disabled
archivedRetired, preserved for history

Run statuses

StatusDescription
pendingWaiting for worker to pick up
runningProcessing customers
completedAll customers processed
completed_with_errorsFinished but some deliveries failed
failedUnrecoverable error

Role requirements

MethodMinimum role
GET (list/detail)viewer
POST (create/trigger)editor
PUT (update)editor
DELETEadmin