Assigning numbers

Point a tracking number at a campaign, credit its calls to a publisher, put it in a pool — what each choice does to attribution, and every rule that can refuse a move.

After this page you can put a number to work on a campaign, credit its calls to the right partner, understand exactly what an omitted field means when you change one, and read any refusal the platform gives you.

A number answers one question for every call it takes: whose call is this? Assigning the number is how you decide the answer in advance. A number has up to three assignments, and only the first is required.

The three assignments

AssignmentRequired?What it does
CampaignYesEvery call to the number is judged by this campaign's settings and sent down its routing plan. A number with no campaign reaches nobody.
PublisherNoCalls to the number are credited to this publisher and paid on their lane's terms. Leave it empty for media you run yourself — owned media has no publisher and no payout.
PoolNoThe number joins a number pool and is lent to one website visitor at a time. A pooled number should not be printed anywhere.
In the console these are the three sections of the assign drawer: This number rings, Attribute calls to and Part of a pool, with What this number is for underneath for the label.
Assign a number
curl -X PATCH "https://api.buy3.io/api/tracking/numbers/2f6b8c1d-4e5a-4b7c-9d8e-0f1a2b3c4d5e" \
  -H "Authorization: Bearer $BUY3_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "campaignId": "6a2d1f0e-8b7c-4c55-a1d3-0e9f8a7b6c5d",
    "publisherId": "c4e1a2b3-9d8f-4f6e-b5a4-1c2d3e4f5a6b",
    "label": "Northwind — Dallas landing page"
  }'

What an omitted field means

A change is a patch, so leaving a field out is not the same as sending null. The rules are short, and they exist so that a half-specified move can never leave a number attributed to somebody who has no deal on its new campaign.

  • A field the request does not mention keeps its value.
  • campaignId: null clears the job entirely: the number becomes unassigned, and the publisher and the pool go with it. Both are facts *about* a campaign, and neither means anything once it is gone.
  • Moving to another campaign drops the publisher and the pool unless the same request restates them. Carrying them across silently would leave a number credited to a partner with no lane on its new campaign, or rotating in a pool that feeds a different one.
  • poolId on a number that has no campaign yet implies the pool's campaign, because the pool already says which one that is.
  • The label survives all of it.
Take a number off everything
curl -X PATCH "https://api.buy3.io/api/tracking/numbers/2f6b8c1d-4e5a-4b7c-9d8e-0f1a2b3c4d5e" \
  -H "Authorization: Bearer $BUY3_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "campaignId": null }'

What can refuse a move

RefusalWhy
The campaign is not a call-tracking campaignA tracking number on a campaign of another kind would find no routing plan and turn every caller away. It answers as though the campaign does not exist.
The campaign is archivedNothing can be pointed at it.
The publisher has no lane on that campaignA lane is the agreement. Without one there are no payout terms, so a call credited to them could never be priced. Open the lane first — see Publishers overview.
A publisher with no campaignA number with no campaign cannot carry a publisher or a pool. The response names the field.
pool_campaign_mismatchThe pool belongs to another campaign.
pool_publisher_mismatchA pooled number carries the pool's publisher. A pool is one traffic source by definition, so change it on the pool, never on one of its numbers.
number_is_fallbackThe number is a pool's fallback, and a fallback has to stay out of rotation — it is what visitors see when the pool has run out. Give that pool another fallback first.
The number is doing another jobAn inbound line, an agent's own line or a quarantined number is listed here — the workspace pays for it — and is never reassigned from here. The message says where to go.
The number is releasedIt has gone back to the carrier.
409 — a refusal a program can branch on
{
  "error": "\"BlueSky landing pages\" is a pool of another campaign — a number can only rotate in a pool of the campaign it points at",
  "code": "pool_campaign_mismatch",
  "details": {
    "poolId": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
    "poolCampaignId": "9b8a7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
  },
  "requestId": "req_7c6b5a4938271605"
}

Warnings you get back

A successful move can still be worth reading. The answer carries a warnings array — things that are true, that nobody asked about, and that would otherwise be discovered by a caller.

200 — moved, with something to say
{
  "number": {
    "id": "2f6b8c1d-4e5a-4b7c-9d8e-0f1a2b3c4d5e",
    "e164": "+12145550142",
    "formatted": "(214) 555-0142",
    "status": "active",
    "role": "tracking",
    "label": "Northwind — Dallas landing page",
    "campaign": { "id": "6a2d1f0e-8b7c-4c55-a1d3-0e9f8a7b6c5d", "name": "Acme Health inbound", "status": "live" },
    "publisher": { "id": "c4e1a2b3-9d8f-4f6e-b5a4-1c2d3e4f5a6b", "name": "Northwind Media" },
    "pool": null,
    "webhookStatus": "pending",
    "webhookError": null
  },
  "warnings": [
    "The carrier is not delivering this number's calls to the platform yet. Calls to it will not be tracked until that is fixed.",
    "\"BlueSky landing pages\" no longer has a fallback number — this one stopped reaching its campaign."
  ]
}
WarningWhat to do
The carrier is not delivering this number's calls to the platform yetThe number looks healthy everywhere and takes no calls. Assigning a number re-attempts the wiring automatically; if it still fails, the message carries the carrier's own error and support can take it from there.
A pool no longer has a fallback numberThis number was that pool's fallback and has stopped reaching its campaign, so the pool has none. Choose another before the pool next runs out.
A live campaign now has no number pointing at itYou took the last number off a campaign that is still live. Nobody can call it until you assign another.
The console's inventory list shows the wiring state beside the number too: Connecting while it is being set up and Not connected when it has failed.

One number per source

Attribution by number is only as fine as your numbers. One number on every advert tells you the campaign got a call; one number per placement tells you which placement earned it. Where a single placement is a web page with many visitors, a number pool takes it one step further and tells you which visit.

What the number knows arrives on each of its calls as tags, and each tag records where it came from. Tags from the number can be read by filters, grouped in reports and sent on in webhooks and pixels.

The tags on a call from a labelled, tagged number
{
  "tags": {
    "number_label": "Northwind — Dallas landing page",
    "placement": "radio",
    "region": "north",
    "number_tags": "seasonal,reprint",
    "dialed_number": "+12145550142",
    "publisher": "Northwind Media",
    "caller_area_code": "214",
    "caller_state": "TX"
  },
  "tagSources": {
    "number_label": "number",
    "placement": "number",
    "region": "number",
    "number_tags": "number",
    "dialed_number": "system",
    "publisher": "system",
    "caller_area_code": "system",
    "caller_state": "system"
  }
}
  • number — the number's label and its own tags, set when you bought it.
  • dni — the visitor's URL parameters, when the number came from a pool.
  • system — what the platform read off the call itself: the number dialled, the publisher's name, the caller's area code and state.
  • The order is dni, then number, then system, so nothing a web page can put in a query string ever replaces a fact the platform observed.

Moving a number is safe for history

A call keeps the campaign and the publisher it had when it happened. Moving a number to another campaign changes where the next call goes and nothing about the last one, and every move is written to the activity log with the old value and the new.

A worked example

Northwind Media are already sending calls to Acme Health inbound by pinging. They now want a number of their own for a landing page they run.

  1. Check the lane exists. They already have one on that campaign, so a number can be credited to them.
  2. Buy a number in the right area code. It lands unassigned.
  3. Assign it: campaign Acme Health inbound, publisher Northwind Media, label Northwind — Dallas landing page. It starts routing immediately.
  4. Two weeks later they want per-visitor attribution on that page. You create a pool on the same campaign with Northwind as its publisher, then set poolId on the number — the publisher already matches the pool's, so nothing is refused.
  5. At the end of the flight, the whole placement stops. Sending { "campaignId": null } takes the number off the campaign, out of the pool and off the publisher in one move, and the rent carries on until you take it out of service.

Next steps