HCC Docs

Campaigns

List campaigns

GET /v1/campaigns campaigns:read

Responses

  • 200

    The campaigns of this environment

    Fields
    • data Campaign[] required
      Fields
      • id string required
      • name string required
      • version string required
      • hooks string[] required

        The hooks this version defines

      • steps object[] required

        The sequence, in order

      • enrollment object required

        Its .enroll: which leads it takes by itself, and whether a lead that left can start over

      • status "running" | "paused" required
      • pausedReason "manual" | "not_started" | "hook_failing" | "needs_deploy" | "needs_deploy_held" | "billing" | null required
      • counts object required

        Leads per state, dials, and exit_<reason> for how leads left. Kept as counters, so reading it is cheap.

      • warnings string[]

        On a deploy: what this change does to leads mid-sequence.

      • createdAt string required
      • updatedAt string required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Register campaigns

PUT /v1/campaigns campaigns:write

What hcc deploy sends. A campaign is its name and which hooks it defines; the logic is in your code. A new campaign starts paused in every environment, until someone resumes it, and a deploy never changes the status of one that exists.

Body

  • campaigns object[] required
    Fields
    • name string required
    • version string required
    • hooks "onLead" | "call" | "do" | "goal" | "exit" | "afterCall" | "screenPop" | "onAnswer" | "onVoicemail" | "onNoAnswer" | "onError"[] required
    • steps object[]

      Default [{"kind":"call","target":{"type":"queue"}}].

      Fields
      call
      • kind "call" required
      • name string
      • target object required
      • from string
      wait
      • kind "wait" required
      • name string
      • ms integer required
      do
      • kind "do" required
      • name string
    • enrollment object
      Fields
      • where object

        Default {}.

      • reenroll boolean

        Default true.

    • flow object required
      Fields
      • name string required
      • version string required
      • timeoutMs integer

        100 to 5000.

      • inputSchema object
      • stateSchema object
      • handlers "call.answered" | "call.no_answer" | "call.voicemail" | "call.hangup" | "call.gather" | "call.agent.tool" | "call.agent.ended" | "call.agent.summary" | "call.custom" | "call.transfer.failed" | "call.error"[]

        Default [].

      • customEvents string[]

        Default [].

      • fallbacks object

        Default {}.

      • tools object[]

        Default [].

      • agents object[]

        Default [].

  • mode "report" | "deploy"

    Default "report".

  • endpointUrl string
  • alsoTest boolean

    Default false.

Responses

  • 200

    The registered campaigns

    Fields
    • data Campaign[] required
      Fields
      • id string required
      • name string required
      • version string required
      • hooks string[] required

        The hooks this version defines

      • steps object[] required

        The sequence, in order

      • enrollment object required

        Its .enroll: which leads it takes by itself, and whether a lead that left can start over

      • status "running" | "paused" required
      • pausedReason "manual" | "not_started" | "hook_failing" | "needs_deploy" | "needs_deploy_held" | "billing" | null required
      • counts object required

        Leads per state, dials, and exit_<reason> for how leads left. Kept as counters, so reading it is cheap.

      • warnings string[]

        On a deploy: what this change does to leads mid-sequence.

      • createdAt string required
      • updatedAt string required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Get a campaign

GET /v1/campaigns/{name} campaigns:read

Path

  • name string required

Responses

  • 200

    The campaign

    Fields
    • data Campaign required
      Fields
      • id string required
      • name string required
      • version string required
      • hooks string[] required

        The hooks this version defines

      • steps object[] required

        The sequence, in order

      • enrollment object required

        Its .enroll: which leads it takes by itself, and whether a lead that left can start over

      • status "running" | "paused" required
      • pausedReason "manual" | "not_started" | "hook_failing" | "needs_deploy" | "needs_deploy_held" | "billing" | null required
      • counts object required

        Leads per state, dials, and exit_<reason> for how leads left. Kept as counters, so reading it is cheap.

      • warnings string[]

        On a deploy: what this change does to leads mid-sequence.

      • createdAt string required
      • updatedAt string required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Pause a campaign

POST /v1/campaigns/{name}/pause campaigns:write

No new dials. Calls already up carry on.

Path

  • name string required

Responses

  • 200

    The campaign

    Fields
    • data Campaign required
      Fields
      • id string required
      • name string required
      • version string required
      • hooks string[] required

        The hooks this version defines

      • steps object[] required

        The sequence, in order

      • enrollment object required

        Its .enroll: which leads it takes by itself, and whether a lead that left can start over

      • status "running" | "paused" required
      • pausedReason "manual" | "not_started" | "hook_failing" | "needs_deploy" | "needs_deploy_held" | "billing" | null required
      • counts object required

        Leads per state, dials, and exit_<reason> for how leads left. Kept as counters, so reading it is cheap.

      • warnings string[]

        On a deploy: what this change does to leads mid-sequence.

      • createdAt string required
      • updatedAt string required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Resume a campaign

POST /v1/campaigns/{name}/resume campaigns:write

Dials again, within calling hours and pacing. Refused with a 409 while the campaign needs a deploy.

Path

  • name string required

Responses

  • 200

    The campaign

    Fields
    • data Campaign required
      Fields
      • id string required
      • name string required
      • version string required
      • hooks string[] required

        The hooks this version defines

      • steps object[] required

        The sequence, in order

      • enrollment object required

        Its .enroll: which leads it takes by itself, and whether a lead that left can start over

      • status "running" | "paused" required
      • pausedReason "manual" | "not_started" | "hook_failing" | "needs_deploy" | "needs_deploy_held" | "billing" | null required
      • counts object required

        Leads per state, dials, and exit_<reason> for how leads left. Kept as counters, so reading it is cheap.

      • warnings string[]

        On a deploy: what this change does to leads mid-sequence.

      • createdAt string required
      • updatedAt string required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

A campaign's latest backfill

GET /v1/campaigns/{name}/backfill campaigns:read

Path

  • name string required

Responses

  • 200

    The latest run, or null if there has been none

    Fields
    • data any required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Run existing leads through a campaign

POST /v1/campaigns/{name}/backfill campaigns:write

Runs each lead that matches the campaign's filter, from its .enroll, through its onLead. With no onLead it takes them all, in the database, with no call to your server. It works while the campaign is paused, and nothing dials until it runs: while it's running, the leads it enrolls can be dialed straight away. A lead already in the campaign stays where it is, a lead that left stays out, and a removed lead comes back only if onLead enrolls it and the campaign doesn't say reenroll: false, so it's safe to repeat. It runs only when you ask, never on a deploy or a resume. A 409 if one is already running for this campaign, or if the campaign needs a deploy.

Path

  • name string required

Body

CampaignBackfillRequest

Responses

  • 202

    Started. Follow it with GET

    Fields
    • data CampaignBackfill required
      Fields
      • id string required
      • campaign string required
      • status "running" | "done" | "failed" | "cancelled" required

        failed means the flow endpoint kept failing and it stopped early: retry goes on from where it was. A done run can still have failed leads, which a retry sends again.

      • where object | null required

        The campaign's filter when it started

      • leadsInScope integer required

        How many leads the environment had when it started. The count stops at 1,000,000: see leadsInScopeCapped.

      • leadsInScopeCapped boolean required
      • scanned integer required

        Leads walked, matching the filter or not

      • checked integer required

        Leads that matched. enrolled + skipped + failed reaches this once nothing is on its way.

      • enrolled integer required

        Leads new to the campaign

      • skipped integer required

        Already in it, left for good, on your Do Not Call list, or onLead said no

      • failed integer required

        Leads with no answer, after retries

      • failure string | null required

        Why the latest batch was given up on

      • retryReason string | null required

        What it can't do just now and keeps trying. Only while it's running

      • createdAt string required
      • updatedAt string required
      • finishedAt string | null required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Stop a backfill

POST /v1/campaigns/{name}/backfill/cancel campaigns:write

What was enrolled stays. A 409 if none is running. A batch being answered at that moment can still enroll its leads.

Path

  • name string required

Responses

  • 200

    The run

    Fields
    • data CampaignBackfill required
      Fields
      • id string required
      • campaign string required
      • status "running" | "done" | "failed" | "cancelled" required

        failed means the flow endpoint kept failing and it stopped early: retry goes on from where it was. A done run can still have failed leads, which a retry sends again.

      • where object | null required

        The campaign's filter when it started

      • leadsInScope integer required

        How many leads the environment had when it started. The count stops at 1,000,000: see leadsInScopeCapped.

      • leadsInScopeCapped boolean required
      • scanned integer required

        Leads walked, matching the filter or not

      • checked integer required

        Leads that matched. enrolled + skipped + failed reaches this once nothing is on its way.

      • enrolled integer required

        Leads new to the campaign

      • skipped integer required

        Already in it, left for good, on your Do Not Call list, or onLead said no

      • failed integer required

        Leads with no answer, after retries

      • failure string | null required

        Why the latest batch was given up on

      • retryReason string | null required

        What it can't do just now and keeps trying. Only while it's running

      • createdAt string required
      • updatedAt string required
      • finishedAt string | null required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Retry a backfill's failures

POST /v1/campaigns/{name}/backfill/retry campaigns:write

Sends its failed leads again and, if it stopped early, walks on from where it was. A 409 if one is running, or there is nothing to retry.

Path

  • name string required

Responses

  • 200

    The run

    Fields
    • data CampaignBackfill required
      Fields
      • id string required
      • campaign string required
      • status "running" | "done" | "failed" | "cancelled" required

        failed means the flow endpoint kept failing and it stopped early: retry goes on from where it was. A done run can still have failed leads, which a retry sends again.

      • where object | null required

        The campaign's filter when it started

      • leadsInScope integer required

        How many leads the environment had when it started. The count stops at 1,000,000: see leadsInScopeCapped.

      • leadsInScopeCapped boolean required
      • scanned integer required

        Leads walked, matching the filter or not

      • checked integer required

        Leads that matched. enrolled + skipped + failed reaches this once nothing is on its way.

      • enrolled integer required

        Leads new to the campaign

      • skipped integer required

        Already in it, left for good, on your Do Not Call list, or onLead said no

      • failed integer required

        Leads with no answer, after retries

      • failure string | null required

        Why the latest batch was given up on

      • retryReason string | null required

        What it can't do just now and keeps trying. Only while it's running

      • createdAt string required
      • updatedAt string required
      • finishedAt string | null required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

List a campaign's leads

GET /v1/campaigns/{name}/leads campaigns:read

Path

  • name string required

Query

  • state "queued" | "waiting" | "needs_timezone" | "needs_consent" | "claimed" | "in_call" | "acting" | "deciding" | "step_failed" | "done"
  • limit integer
  • cursor string

Responses

  • 200

    The most recently changed first

    Fields
    • data CampaignLead[] required
      Fields
      • leadId string required
      • phone string required
      • name string | null required
      • state "queued" | "waiting" | "needs_timezone" | "needs_consent" | "claimed" | "in_call" | "acting" | "deciding" | "step_failed" | "done" required
      • priority integer required
      • attempts integer required
      • nextAttemptAt string required
      • lastOutcome string | null required
      • step integer required

        Where it is in the sequence, or what is next

      • stepName string | null required
      • exitReason "goal" | "exit" | "finished" | "removed" | "do_not_call" | null required

        Why it left, once it has

    • nextCursor string | null required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Put leads in a campaign

POST /v1/campaigns/{name}/leads campaigns:write

Straight in line, past onLead, if they match the campaign's filter and aren't on your Do Not Call list. A lead already in the campaign stays put.

Path

  • name string required

Body

  • leadIds string[] required
  • priority integer

    0 to 1000.

Responses

  • 200

    How many were new to it, and how many the campaign's filter or your Do Not Call list turned away

    Fields
    • data object required
      Fields
      • enrolled integer required
      • skipped integer required
  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Take a lead out of a campaign

DELETE /v1/campaigns/{name}/leads/{leadId} campaigns:write

The lead stays. A dial it was ready for is dropped before it happens.

Path

  • name string required
  • leadId string required

Responses

  • 204

    Removed

  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code

Try a parked lead again

POST /v1/campaigns/{name}/leads/{leadId}/retry campaigns:write

A lead parked as step_failed goes back to the step it stopped at, within a minute. For a lead parked just after a call, that means another dial.

Path

  • name string required
  • leadId string required

Responses

  • 202

    On its way

  • 400

    Invalid request

  • 401

    Missing or invalid API key

  • 404

    Not found

  • 429

    rate_limited, or another limit named by error.code