API reference

RTB ping and post

The endpoints a publisher's platform calls to sell you a call in real time: ping for a bid, post to claim it, release it, and — for the buyer — post a conversion.

This is the surface a publisher's system talks to. It is authenticated with a publisher key — one publisher on one campaign — rather than with your API key, and it answers in its own envelope: ok: true with the result, or ok: false with an error code and a message. The walkthrough is in Ping and post; this page is the field-by-field reference.

Base URL and authentication

Base URL
https://api.buy3.io/api/rtb/v1
  • Send the publisher key as Authorization: Bearer b3k_live_…. The key identifies the publisher and the campaign, so neither appears in a request.
  • Bodies are JSON, at most 32 KB.
  • If the key requires it, sign each request with the X-Buy3-Timestamp, X-Buy3-Nonce and X-Buy3-Signature headers — see Keys and security.
  • Every request, accepted or refused, is a row in the ping ledger that you and the publisher can both read.

Rate limits

Pings are limited per key, per minute, hour and day. Responses carry RateLimit-Policy and RateLimit headers; over the limit the answer is 429 with the reject code 1024 and a Retry-After header. The defaults are in Limits and can be changed on each key.

Endpoints

Ping for a bid

POST/api/rtb/v1/ping

Describe a call and get back what it is worth. A win reserves a slot for that caller until the bid expires; it does not return a destination — claim the bid with a post for that. The same request is also accepted as a GET with the fields as query parameters, for platforms that cannot send a body. A GET is not a way round signing: on a key that requires signatures it is signed over its raw query string, exactly as it was sent, without the leading ?.

Publisher key. Send Authorization: Bearer <publisher key> — the key issued for one publisher on one campaign.

Request body

NameTypeDescription
callerIdOptionalstringThe caller's number. Required when the campaign requires a caller ID; a bid made without one carries a warning.E.164, such as +12145550142
stateOptionalstringThe caller's state, as a two-letter code.
zipOptionalstringThe caller's ZIP code.
cityOptionalstringThe caller's city.
sipOkOptionalbooleanWhether you can deliver the call over SIP. When true, the post may answer with a sipAddress.
exposeCallerIdOptionalbooleanWhether the caller's number may be passed on to the buyer.
publisherRefOptionalstringYour own reference for this lead. It is stored with the call and shown in your portal.
externalCallIdOptionalstringYour phone system's id for the call.
testOptionalbooleanMarks the ping as a test. The response carries a warning saying so.
tagsOptionalobjectKey-value pairs describing the caller. Any other top-level scalar field you send is kept as a tag too, so an existing payload usually works unchanged.at most 40 tags · key up to 64 characters, value up to 512

Example request

curl -X POST "https://api.buy3.io/api/rtb/v1/ping" \
  -H "Authorization: Bearer b3k_live_your_publisher_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
  -d '{
    "callerId": "+12145550142",
    "state": "TX",
    "zip": "75201",
    "sipOk": true,
    "publisherRef": "lead-88231",
    "tags": { "utm_source": "search", "age_band": "65plus" }
  }'

Responses

  • 200A bid. expiresInSeconds is how long the price and the reserved slot are held.
  • 200 (no bid)No bid. reject.code is one of the reject codes and never changes meaning.
{
  "ok": true,
  "auctionId": "0b9c6c1e-7f0a-4a55-9d0e-3c1b8a2f4d10",
  "bidId": "0f8fad5b-d9cb-469f-a165-70867728950e",
  "payout": 38.5,
  "payoutCents": 3850,
  "currency": "USD",
  "expiresInSeconds": 30,
  "expiresAt": "2026-09-20T14:03:57.000Z",
  "expiresAtEpochMs": 1789913037000,
  "nextStep": "post",
  "terms": [
    {
      "code": 101,
      "description": "Call must connect"
    },
    {
      "code": 100,
      "description": "Minimum connected duration 90 seconds",
      "seconds": 90
    }
  ],
  "campaign": {
    "id": "c2b7e1a0-6f3d-4b1e-8a55-0d9c4e7f1a23",
    "name": "Medicare — inbound"
  }
}

Errors

StatusCodeWhen
401missing_keyNo Authorization: Bearer header.
401invalid_keyThe key is not recognised, or has been revoked and its grace period is over.
4014000–4003The key requires signed requests and the signature, timestamp or nonce did not check out. See Keys and security.
403wrong_protocolThe key is not enabled for this protocol.
403publisher_not_liveThe publisher is not live.
403campaign_not_liveThe campaign is not live.
403ip_not_allowedThe request came from outside the key's IP allowlist.
400malformed_requestThe body is not valid JSON.
409bid_in_flightAn identical ping is being scored right now. Wait for it instead of sending it again.
409caller_already_reservedA live bid is already held for this caller on this campaign.
429rate_limitedThe key is over one of its ping limits. Retry-After says how long to wait.

Post to claim a bid

POST/api/rtb/v1/post

Claim a winning bid before it expires and receive the destination to send the caller to. The Idempotency-Key header is required: a retried post must never create a second call for the same caller, and you cannot detect that from your side. If the winning target has filled since the ping, the platform tries the runners-up before giving up, and says so with failedOver.

Publisher key. Send Authorization: Bearer <publisher key> — the key issued for one publisher on one campaign.

Request body

NameTypeDescription
bidIdRequireduuidThe bidId from the ping.
callerIdOptionalstringThe caller's number. If the ping carried one, this must match it.up to 32 characters
externalCallIdOptionalstringYour phone system's id for the call.up to 120 characters
tagsOptionalobjectFurther tags learned since the ping.

Example request

curl -X POST "https://api.buy3.io/api/rtb/v1/post" \
  -H "Authorization: Bearer b3k_live_your_publisher_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 1b4e28ba-2fa1-41d2-883f-0016d3cca427" \
  -d '{
    "bidId": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "callerId": "+12145550142",
    "externalCallId": "pbx-5531902"
  }'

Responses

  • 201The bid is claimed. Send the caller to sipAddress if you can deliver over SIP, otherwise to phoneNumber. On a call tracking campaign phoneNumber is always a number of the platform's own — your lane's tracking number, or the campaign's ingress number — never the buyer's line, because a caller who reaches the buyer directly is a call the platform never sees and nobody is paid for. postback is for the buyer — see the conversion endpoint below.
{
  "ok": true,
  "callId": "5f0c1c8e-2a44-4d0a-9d0f-7b3f0a6c9e12",
  "ref": "CL-204817",
  "bidId": "0f8fad5b-d9cb-469f-a165-70867728950e",
  "payout": 38.5,
  "payoutCents": 3850,
  "sipAddress": "sip:0f8fad5bd9cb469fa16570867728950e@sip.example.net",
  "phoneNumber": "+18335550119",
  "phoneNumberNoPlus": "18335550119",
  "expiresInSeconds": 30,
  "expiresAt": "2026-09-20T14:04:27.000Z",
  "terms": [
    {
      "code": 101,
      "description": "Call must connect"
    },
    {
      "code": 100,
      "description": "Minimum connected duration 90 seconds",
      "seconds": 90
    }
  ],
  "postback": {
    "url": "https://api.buy3.io/api/rtb/v1/conversion",
    "key": "b3p_4f1d2c3b4a5e6f70"
  }
}

Errors

StatusCodeWhen
401missing_keyNo Authorization: Bearer header.
401invalid_keyThe key is not recognised, or has been revoked and its grace period is over.
4014000–4003The key requires signed requests and the signature, timestamp or nonce did not check out. See Keys and security.
403wrong_protocolThe key is not enabled for this protocol.
403publisher_not_liveThe publisher is not live.
403campaign_not_liveThe campaign is not live.
403ip_not_allowedThe request came from outside the key's IP allowlist.
400idempotency_key_requiredNo Idempotency-Key header was sent.
400validation_errorbidId is missing or is not a UUID.
404unknown_bidNo such bid for this key.
409bid_already_claimedThe bid has already been claimed and is no longer open. A straightforward repeat of a post that succeeded is not this error — it answers 201 with the original body again.
409caller_id_mismatchThe callerId does not match the one the bid was made for.
409no_capacity_at_postThe winning target filled before the post, and no runner-up could take the call.
409no_destinationA call tracking lane with no tracking number of the platform's own and no SIP address to send the caller to. Refused before a slot is taken or a call is written, rather than answered with a destination that would not be tracked. Carries reject: 1018 and warning 250.
410bid_expiredThe bid's expiresInSeconds had passed.

Release a bid

POST/api/rtb/v1/release

Give a bid back when the caller is not coming — they hung up, or you sold the call elsewhere. It frees the reserved slot immediately instead of when the bid expires. Releasing a bid that is already closed is not an error.

Publisher key. Send Authorization: Bearer <publisher key> — the key issued for one publisher on one campaign.

Request body

NameTypeDescription
bidIdRequireduuidThe bid to release.
reasonOptionalstringWhy, in your own words. Shown in the ping ledger.up to 120 characters

Example request

curl -X POST "https://api.buy3.io/api/rtb/v1/release" \
  -H "Authorization: Bearer b3k_live_your_publisher_key" \
  -H "Content-Type: application/json" \
  -d '{ "bidId": "0f8fad5b-d9cb-469f-a165-70867728950e", "reason": "caller_hung_up" }'

Responses

  • 200The bid was released.
  • 200 (already closed)The bid had already been claimed, released or expired. status says which.
{
  "ok": true,
  "released": true
}

Errors

StatusCodeWhen
401missing_keyNo Authorization: Bearer header.
401invalid_keyThe key is not recognised, or has been revoked and its grace period is over.
4014000–4003The key requires signed requests and the signature, timestamp or nonce did not check out. See Keys and security.
403wrong_protocolThe key is not enabled for this protocol.
403publisher_not_liveThe publisher is not live.
403campaign_not_liveThe campaign is not live.
403ip_not_allowedThe request came from outside the key's IP allowlist.
404unknown_bidNo such bid for this key.

Post a conversion

POST/api/rtb/v1/conversion

The buyer's postback: tell the seller that a call they received converted. It takes no publisher key — the buyer never holds one — and is authorised by the per-call key that came back from the post and travelled to the buyer with the call. A call takes one conversion.

No API key. No Authorization header. The request authenticates itself with a value in its body or URL, described below.

Request body

NameTypeDescription
keyRequiredstringThe per-call postback key, b3p_….
callIdRequireduuidThe call being reported on.
convertedOptionalbooleanWhether the call converted. Defaults to true.
valueOptionalnumberWhat the conversion was worth, in dollars.0 or more
dispositionOptionalstringYour outcome label, such as policy_sold.up to 60 characters
reasonOptionalstringFree-text detail.up to 200 characters
occurredAtOptionaldateWhen the conversion happened. Defaults to now.

Example request

curl -X POST "https://api.buy3.io/api/rtb/v1/conversion" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "b3p_4f1d2c3b4a5e6f70",
    "callId": "5f0c1c8e-2a44-4d0a-9d0f-7b3f0a6c9e12",
    "converted": true,
    "value": 420.00,
    "disposition": "policy_sold"
  }'

Responses

  • 200The conversion was recorded and the call re-settled.
{
  "ok": true,
  "callId": "5f0c1c8e-2a44-4d0a-9d0f-7b3f0a6c9e12",
  "ref": "CL-204817",
  "billable": true,
  "payoutCents": 3850
}

Errors

StatusCodeWhen
400malformed_requestThe body is not valid JSON.
404unknown_callNo call matches that callId and key. A wrong key answers 404, not 403, so the endpoint cannot be used to discover which call ids exist.
409already_convertedThe call already has a conversion. convertedAt says when.
410window_closedConversions close 72 hours after the call ends.

Check a key

GET/api/rtb/v1/whoami

Everything an integrator would otherwise have to ask you: which publisher and campaign the key belongs to, whether both are live, the key's limits, whether it must sign requests, its IP allowlist and the exact URLs to call. A recognised but blocked key answers 200 with ok: false and the problem named; only an unknown key is an error.

Publisher key. Send Authorization: Bearer <publisher key> — the key issued for one publisher on one campaign.

Example request

curl "https://api.buy3.io/api/rtb/v1/whoami" \
  -H "Authorization: Bearer b3k_live_your_publisher_key"

Responses

  • 200The key's identity and limits.
{
  "ok": true,
  "problem": null,
  "protocol": "rtb_v1",
  "environment": "live",
  "publisher": {
    "id": "7d3c2b1a-0f9e-4d8c-b7a6-5e4d3c2b1a09",
    "name": "Brightpath Media",
    "status": "active"
  },
  "campaign": {
    "id": "c2b7e1a0-6f3d-4b1e-8a55-0d9c4e7f1a23",
    "name": "Medicare — inbound",
    "status": "live",
    "requireCallerId": false,
    "requiredTags": []
  },
  "key": {
    "prefix": "b3k_live_9f2a",
    "label": "Production",
    "requireSignature": false,
    "ipAllowlist": []
  },
  "limits": {
    "perMinute": 120,
    "perHour": 5000,
    "perDay": 50000,
    "maxLiveBidsPerCaller": 1,
    "bidTtlSeconds": 30
  },
  "endpoints": {
    "ping": "https://api.buy3.io/api/rtb/v1/ping",
    "post": "https://api.buy3.io/api/rtb/v1/post",
    "release": "https://api.buy3.io/api/rtb/v1/release",
    "conversion": "https://api.buy3.io/api/rtb/v1/conversion"
  }
}

Errors

StatusCodeWhen
401missing_keyNo Authorization: Bearer header.
401invalid_keyThe key is not recognised.

Look a call up

GET/api/rtb/v1/calls/:ref

For the buyer: fetch a call's details with the per-call postback key, whatever their phone system stripped from the SIP headers on the way. The caller's number is included only when the campaign exposes caller ID and the call has connected — a buyer who never took the call has no claim on the number.

No API key. No Authorization header. The request authenticates itself with a value in its body or URL, described below.

Path parameters

NameTypeDescription
refRequiredstringThe call's public reference, such as CL-204817, or its id.

Query parameters

NameTypeDescription
keyOptionalstringThe per-call postback key, when it cannot be sent as Authorization: Bearer <key>.

Example request

curl "https://api.buy3.io/api/rtb/v1/calls/CL-204817" \
  -H "Authorization: Bearer b3p_4f1d2c3b4a5e6f70"

Responses

  • 200The call, as much of it as the buyer is entitled to.
{
  "ok": true,
  "ref": "CL-204817",
  "callId": "5f0c1c8e-2a44-4d0a-9d0f-7b3f0a6c9e12",
  "status": "completed",
  "startedAt": "2026-09-20T14:03:21.000Z",
  "answeredAt": "2026-09-20T14:03:27.000Z",
  "caller": {
    "number": "+12145550142",
    "state": "TX"
  },
  "campaign": {
    "id": "c2b7e1a0-6f3d-4b1e-8a55-0d9c4e7f1a23",
    "name": "Medicare — inbound"
  },
  "publisherRef": "lead-88231",
  "tags": {
    "utm_source": "search",
    "age_band": "65plus"
  },
  "bid": {
    "id": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "amountCents": 4400,
    "durationSeconds": 90
  }
}

Errors

StatusCodeWhen
401missing_keyNo key was sent in the header or the query.
404unknown_callNo call matches that reference and key.