Campaigns overview

What a tracking campaign is, the gates every call passes before a buyer is considered, every campaign setting with its range and default, how a campaign goes live and what an API key can change.

After this guide you will be able to set a campaign up end to end: choose its settings knowingly, take it live without being refused, pause and resume it from a script, and say why a call to one of its numbers never reached a buyer.

A campaign is one stream of calls with one set of rules: one offer, one vertical, one group of tracking numbers. It exists so that the questions that are about the *call* — is it inside hours, has this person called before, what happens if nobody answers — are asked once, in one place, before the questions that are about a *buyer*. Those belong to the campaign's routing plan.

Two ways a call reaches a campaign

  • Somebody dials one of its numbers. The tracking number says which campaign the call belongs to, and — when the number is tied to a publisher or sits in a number pool — who sent it. This is the path the rest of this page describes.
  • A publisher pings it, wins and sends the call. The publisher's platform asks for a bid first, and the call that follows is routed by the same plan, with the auction standing in for the gates. See How RTB works.

The gates a call passes first

Before a single target is looked at, a dialled call is tested against eight gates, always in this order. The first one it fails ends the call there, with that reason code on it. Every call gets a row in the call log, including the ones that went nowhere.

GateDecided byReason if it failsCaller gets
Is the workspace's plan active, and does it include call tracking?Billing and usageworkspace_inactiveA busy signal
Is the wallet funded?Walletworkspace_unfundedA busy signal
Is the campaign live?Status, belowcampaign_not_liveA busy signal
Is the caller blocked?Blocked callerscaller_blockedA busy signal
Did the caller hide their number?anonymousPolicyanonymous_blockedA busy signal
Is the campaign inside its hours?hoursSchedulecampaign_closedThe unrouted action
Is the campaign under its caps?dailyCap, concurrencyCapcampaign_cappedThe unrouted action
Has this caller reached a buyer here before?repeatCallerPolicyrepeat_blockedA busy signal
"A busy signal" means the call is refused without being answered, so no minute starts. "The unrouted action" is the campaign's unroutedAction: hang up, a spoken message or a forward.

When the wallet gate fails, the workspace's owners are notified and a wallet.low event is sent — at most once an hour, however many callers are turned away in it.

The settings

FieldValuesWhat it does
name1–120 charactersRequired.
verticalIdone of the platform's verticals, or one of your ownRequired, and set once: a campaign cannot be moved to another vertical. Create a new campaign instead.
descriptionup to 300 charactersA note for your team.
routingModepriority (default), weighted, highest_bidHow the routing plan is put in order for each call. See The three routing modes.
recordCallstrue (default), falseWhether calls on this campaign are recorded. Read once, when the call arrives.
repeatCallerPolicyallow (default), block, same_targetWhat happens to a caller who has already reached a buyer on this campaign. See Repeat and blocked callers.
dedupeWindowSeconds0–7 776 000 (90 days); default 0How far back the repeat-caller policy looks. 0 means for ever.
anonymousPolicyallow (default), blockWhether a caller with a withheld number is routed.
unroutedActionhangup (default), message, forwardWhat a caller gets when the campaign wanted the call and could not place it. See The unrouted action.
unroutedMessageup to 500 charactersRequired when the action is message.
unroutedForwardE164a phone number in international formatRequired when the action is forward.
dialTimeoutSeconds5–120; default 18How long a destination rings when the target does not set a ring time-out of its own.
failoverBudgetSeconds10–180; default 45How long the platform may go on starting new attempts. Never shorter than dialTimeoutSeconds. See The failover budget.
dailyCap0–1 000 000; default 0Calls a day, on the workspace's calendar day. 0 is unlimited.
concurrencyCap0–100 000; default 0Calls in progress at once. 0 is unlimited.
hoursSchedulea schedule, or null (default)When the campaign takes calls. null is always open. See Hours of operation.
timezonean IANA zone such as America/ChicagoThe clock the hours run on. It is stored inside the schedule, so it has no effect on a campaign with no schedule.
statesup to 62 two-letter codes; [] is every stateWhich caller states the campaign bids on when a publisher pings it. A dialled call is not refused by this list — use each target's accepted states for that.
Cross-field rules are judged on the campaign as it will be after the change: switching unroutedAction to forward is refused unless a forward number is already there or arrives in the same request.

A campaign also shows a routingKeyPrefix. It is minted by the platform, read-only, and is what to quote to support when a question is about this campaign.

Status

StatusMeaning
draftBeing built. Every new campaign starts here. Its numbers do not route.
liveRouting. Every call to one of its numbers runs the gates and the plan.
pausedNot routing. Callers get a busy signal and the call is logged with campaign_not_live.
restrictedSet by platform staff, and only staff can lift it. You can read it; you cannot set it.
archivedHistory. It no longer counts against your plan's campaign allowance.

Status is changed by its own request, never as a side effect of editing a setting, so a settings change cannot switch a campaign on or off by accident. A change to the status a campaign already has answers changed: false and does nothing. These changes are refused, each with a 409 that says what to do instead:

  • Going live while not ready. The answer carries details.blockers — the whole list, not just the first. There are exactly two: no active tracking number points at the campaign, and the routing plan has no active route to an active target.
  • Archiving a live campaign. Pause it first.
  • Archiving while numbers still point at it. They would go on ringing into a campaign nobody can see, and go on being rented. Move or release them; details.numbers says how many.
  • Taking an archived campaign anywhere but draft. Restoring re-checks your plan's campaign allowance, so it can also answer 402.

An optional note of up to 500 characters is stored as the campaign's statusNote — "paused for the weekend" — and cleared when the campaign goes live. Every status change is written to the activity log.

The readiness checklist

A campaign's detail carries a checklist: the journey from nothing to a routed call, each step a fact the server checked rather than a box somebody ticked. Two steps are blocking — they are the two a launch is refused on — and one is optional.

StepDone whenBlocks going live
Add a buyerThe workspace has at least one buyer.No
Add a targetThe workspace has at least one target.No
Put a target in the routing planThe plan has an active route to an active target.Yes
Point a tracking number at the campaignAn active tracking number is assigned to it.Yes
Add a publisher laneOnly if somebody else sends you this traffic. Your own media needs none.No — optional
Fund the walletThe workspace wallet has a balance.No
Set the campaign liveIts status is live.No
The detail also carries canGoLive, blockers — the sentences a launch would be refused with — and checklist.warnings, such as a plan whose every active target belongs to a buyer that is not active.

An empty wallet does not block a launch on purpose: a campaign may go live on Friday for traffic that starts on Monday. It does stop calls routing, so the checklist says so.

Worked example: a campaign from nothing to live

  1. 1

    Create the campaign

    In the console, open Campaigns and create one. These are the settings for a Medicare enquiry line that is open on weekdays and Saturday mornings, sends a returning caller back to the buyer they spoke to, and reads a message to anybody it cannot place:

    The campaign's settings
    {
      "name": "Medicare enquiries",
      "verticalId": "medicare",
      "description": "Inbound enquiries from search and partner sites",
      "routingMode": "priority",
      "recordCalls": true,
      "repeatCallerPolicy": "same_target",
      "anonymousPolicy": "block",
      "dedupeWindowSeconds": 2592000,
      "unroutedAction": "message",
      "unroutedMessage": "Thank you for calling. Our lines are closed right now. Please call again tomorrow.",
      "dialTimeoutSeconds": 18,
      "failoverBudgetSeconds": 45,
      "dailyCap": 400,
      "concurrencyCap": 0,
      "hoursSchedule": {
        "tz": "America/Chicago",
        "days": {
          "mon": [
            [
              "08:00",
              "20:00"
            ]
          ],
          "tue": [
            [
              "08:00",
              "20:00"
            ]
          ],
          "wed": [
            [
              "08:00",
              "20:00"
            ]
          ],
          "thu": [
            [
              "08:00",
              "20:00"
            ]
          ],
          "fri": [
            [
              "08:00",
              "20:00"
            ]
          ],
          "sat": [
            [
              "09:00",
              "13:00"
            ]
          ],
          "sun": []
        }
      }
    }

    The campaign is created as a draft. The response already tells you what stands between it and a routed call: canGoLive is false, and blockers lists both blocking steps.

  2. 2

    Give it somewhere to send calls

    Add a buyer and a target, then put the target on the campaign's Routing plan tab. See Routing plans.

  3. 3

    Give it a number

    Buy a tracking number under Numbers and assign it to the campaign. See Assigning numbers.

  4. 4

    Check it, then go live

    Simulate a call from a caller you choose. When the simulation ends at the target you expect, set the campaign live. canGoLive is now true and the request succeeds.

Pause and resume from a script

Creating a campaign, editing its settings, launching a draft and archiving are acts for a person in the console. An API key can do the things an integration needs day to day: read campaigns (campaigns:read), replace a routing plan, and pause and resume a campaign that is already live or paused (campaigns:write).

curl -X POST "https://api.buy3.io/api/v1/campaigns/6a2d1f0e-8b7c-4c55-a1d3-0e9f8a7b6c5d/status" \
  -H "Authorization: Bearer $BUY3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "paused", "note": "Buyers closed for the public holiday" }'

A resume passes the same readiness check as a launch. If somebody released the campaign's last number while it was paused, the answer is:

409 — not ready
{
  "error": "That campaign is not ready to take calls yet",
  "code": "conflict",
  "details": {
    "blockers": [
      "No tracking number points at this campaign — buy or assign one first",
      "The routing plan has no active target — add one, or every caller goes unrouted"
    ]
  },
  "requestId": "5d1c0d2e-8a4f-4c0b-9e1d-2f3a4b5c6d7e"
}

Asking a key to set any other status, or to change a campaign that is a draft or archived, answers 409 with details.allowed listing live and paused. The full request and response shapes are in the Campaigns API reference.

Next steps