Skip to main content
Give us a list of numbers, an assistant, and a goal. We call everyone on the list, retry the ones we missed, and hand back what happened, per person. That’s a campaign, and it’s how most of our customers use Uplift: order confirmations, payment reminders, event invitations, lead qualification.

What you’d build yourself, and what a campaign does instead

You can dial a list with the calling API alone, and plenty of people start there. Here’s what we take over when you use a campaign: Everything else is the same call: the same assistant, the same session record, the same four webhooks, with a campaignId on each one.

Your first campaign

All of this is in the portal too. Over the API it’s five requests. Fill in a draft in any order and update it section by section. Each update sends the whole section. Launch rejects a draft with no assistant, or a static one with no list. It doesn’t check the goal or the window, so set both first.
1

Make the contact list

Create a contact list from pasted rows, an uploaded file, or a Google Sheet. We drop bad numbers, collapse duplicates by number, and tell you how many made it. Keep the listId.
2

Create the campaign

Create a campaign with mode: bounded, the assistant that dials, the goal, the list, a calling window, and a retry policy.
A payment reminder run, one line, three attempts
The goal picks which tool the agent uses to record the outcome. A payment reminder gets record_payment_promise, an order confirmation gets record_order_confirmation. Goals & scorecards has the rest. Send all three fields of the retry policy, or none. We ignore a partial one and apply the defaults: three attempts, ten minutes and then an hour apart. They retry on no answer, busy, voicemail, silent pickups, unreachable, and failed dials. Leave lines at 1 until your account has more. Scheduling & retries covers the details.
No calling window means we dial around the clock. Set one before you launch.
3

Add a scorecard

Optional for launch, and I recommend it. A scorecard is a set of rules that add up to 100 points, and we grade every connected call against it. The grade is the score and sentiment on the calls list. Without one we grade nothing. Today that means the results list stays empty and only call.completed fires. Scorecards shows how to write one. The scorecard goes on config.scorecard, on create or in an update.
4

Launch

Launch now, or schedule a time. Launch copies the list into the campaign, so rows added to the list afterwards never dial.
5

Watch it, then read the results

Get the campaign for state. List its calls for one row per contact, dialed or not, with the attempts so far, the next due time, and the score once graded. Add ?include_summary=true and each row carries its call’s summary. When the list runs out the campaign completes on its own.Results has one row per call with a recorded outcome: a promise to pay, a booking, a qualified lead. Stats has the totals. Each call’s callId is a session id, so percent-encode it and read the call in full. Or don’t poll at all: the webhooks deliver each call as it lands.

Where your contacts come from

Three ways in, and all of them end in a listId:
  • Paste rows. Put a name and a number per line straight in the create request, like the example above.
  • Upload a file. Send a CSV or an Excel .xlsx file, check the column mapping we detected, then create the list from the uploadId.
  • Link a Google Sheet. Share the link, or connect a private sheet through Google. We pull it once into a list.
A row needs a name and a phone number. Every other column goes to the model with the call: order number, amount due, crop, whatever the call needs. Type the values the way you want them said. Contacts covers the column rules, and Variables shows exactly what the model sees.

Static or continuous

mode is fixed at creation. It’s the one thing a draft can’t change.
  • Static, bounded in the API, dials a list you have today and completes when the list is done. This month’s dues. Make the list, create, launch or schedule, read the results.
  • Continuous takes contacts for as long as it runs and ends when you close it. Every new order. Create, launch with nothing, append as events happen, close.
Static vs continuous campaigns has the full comparison, including what each mode lets you change after launch.

Continuous, driven by your system

This is the same campaign, except your system feeds it. Create it with mode: continuous and no list, then launch it. It sits in running with nothing to do until you send work. On every event on your side, append contacts:
A new order, appended the moment it's placed
  • Send an externalRef. Your order id. We tell contacts apart by it. Send the same ref while the call is still pending and nothing changes. Send it again once the contact is done and we queue a fresh call, so a reorder next week works. Without it, each request enrolls the number again.
  • Append up to a thousand at a time. The contacts dial right away, inside the window. We skip a bad row, and the response says which and why.
  • Close it when the source dries up. Close stops new contacts, lets the queue and the retries finish, and completes. There’s no undo.
Every webhook carries the campaignId and the call id embeds the contact, so your endpoint can tie a call.completed back to the order that caused it. That’s the whole loop: order placed, append, call, result.

Tech details for techies

  • One line, one call at a time. The dialer looks for work every five seconds and dials as lines free up. On one line, figure a few dozen attempts an hour. An unanswered dial frees the line in about a minute. A conversation holds it for the call plus grading. A list of three hundred is a day or more once you count retries. Phone numbers & concurrency is where more lines come from.
  • Out of credits pauses the campaign. statusMessage says so. Top up, then resume.
  • A deleted assistant pauses it too. statusMessage reads Paused: assistant version not found, and that attempt counts. Once a campaign is scheduled or launched its assistant can’t change, so start a new campaign.
  • A campaign dials the assistant’s published version. Publish, and the next dial uses the new one. To hold a campaign on one version, set config.assistantVersion to its number — see Draft and publish.
  • Pause stops new dials only. Calls already up finish and get graded. Retries keep their times and go out after resume.
  • A campaign runs once. When it completes there’s no relaunch. Next month’s dues are a new campaign.
  • Stats sample the thousand most recently touched contacts. The call counters are exact, but the contact counts (attempted, retrying, exhausted) stop there. For a bigger campaign, page through the calls list.