osmTalk Docs
Campaigns

Scheduling & Retries

Control when calls go out, how concurrency is shared, and what happens on no-answer.

Campaigns have four scheduling levers: when to start, what hours to dial, how many calls in parallel, and how to retry.

When to start

ModeBehavior
start immediatelyCampaign goes to running right after you POST /start. First calls go out at the next 15-second dialer tick.
scheduledStartAtCampaign stays in scheduled until that timestamp; then auto-transitions to running.
{
  "scheduledStartAt": "2026-05-08T09:00:00+05:30"
}

Dialing window (TCPA / TRAI compliance)

Most jurisdictions restrict when you can call. osmTalk enforces a per-campaign dialing window in the recipient's timezone — calls outside the window are skipped and resumed when the window reopens.

{
  "schedule": {
    "timezone": "Asia/Kolkata",
    "windowStart": "10:00",
    "windowEnd": "19:00",
    "weekdays": [1, 2, 3, 4, 5]
  }
}
FieldPurposeDefault
timezoneIANA zone (e.g. Asia/Kolkata, America/New_York)Asia/Kolkata
windowStart / windowEnd24-hour HH:MM strings09:00 / 19:00
weekdaysArray of 0-6 (Sun=0) — days when dialing is allowed[0,1,2,3,4,5,6]

The dialer evaluates this on every tick. Pause a campaign during banned hours costs nothing — the campaign just sits idle and resumes automatically.

US TCPA quick rule

For US recipients, the safe window is 8 AM – 9 PM local, no calls on federal holidays. Use:

{ "schedule": { "timezone": "America/New_York", "windowStart": "08:00", "windowEnd": "20:30", "weekdays": [1,2,3,4,5] } }

(Conservative — caps at 8:30 PM to avoid edge cases.)

India TRAI

Outbound commercial calls in India are restricted to 09:00 – 21:00 local. Default values are already safe.

Concurrency

SettingScopeCaps at
maxConcurrentPer-campaignOrg cap (default 15)
MAX_CONCURRENT_CALLS_PER_ORG envPer-orgGlobal cap
MAX_CONCURRENT_CALLS envPlatform-wideDeepgram PAYG limit (45)

Example: org cap = 15, and you have two campaigns running each with maxConcurrent: 10. The dialer respects both — you'll see up to 10 calls per campaign and up to 15 in total org-wide.

If you've configured an external dialer at the carrier level (e.g., a predictive dialer queue), set maxConcurrent: 1 per campaign and let the carrier handle pacing.

Retry policy

When a call ends in no_answer, busy, or failed, the lead can be re-dialed:

{
  "retryPolicy": {
    "maxAttempts": 3,
    "backoffMinutes": 60,
    "retryOn": ["no_answer", "busy"]
  }
}
FieldPurposeDefault
maxAttemptsHard cap including the first attempt3
backoffMinutesWait between attempts60
retryOnWhich outcomes trigger a retry["no_answer", "busy"]

Possible retryOn values: no_answer, busy, failed, voicemail. Most teams exclude voicemail because the bot already left a message on the first attempt.

When the lead exhausts maxAttempts, its status is set to failed (terminal).

B2B cold outreach:

{ "maxAttempts": 4, "backoffMinutes": 120, "retryOn": ["no_answer", "busy"] }

Renewal reminders:

{ "maxAttempts": 2, "backoffMinutes": 240, "retryOn": ["no_answer"] }

Aggressive recovery (use sparingly):

{ "maxAttempts": 6, "backoffMinutes": 30, "retryOn": ["no_answer", "busy", "failed"] }

Manual control

You can override the scheduler at any time:

# Pause — stops new dials, lets in-flight calls finish
curl -X POST /api/campaigns/{id}/pause

# Resume — accepts new dials at the next tick
curl -X POST /api/campaigns/{id}/resume

# Stop — forces completed; any in-flight calls finish but no new dials
curl -X POST /api/campaigns/{id}/stop

Manual pause + resume respects the dialing window when resumed. There's no way to override the window without editing the campaign.