Outbound RTB Guide v4.1: Selling Calls via Real-Time Bidding
Version: 4.1
Last Updated: April 21, 2026
Audience: Publishers/sellers auctioning calls to multiple buyers
Feedback: [email protected]
Quick Start TL;DR
Outbound RTB in 5 Bullets:
You're the seller — You have calls and want to auction them to buyers
More buyers = higher payouts — Competition drives up bids (1 buyer = discount, not auction)
Start with a template — Use pre-built configurations for major RTB platforms
Test with static values — Put real phone/zip when testing, NOT [CALLER_ID] brackets
Session timeout gotcha — Map ANY fields quickly, save immediately, THEN configure properly (or use templates to skip this entirely)
Table of Contents
What is Outbound RTB?
When to Use Outbound RTB
Prerequisites
How Outbound RTB Works
Configuration Steps
RTB Templates (Quick Start)
Session Timeout Workaround
Testing with Static vs Dynamic Values
Platform-Specific Configuration
Lead Protection (Multi-Step RTB)
Why You Need Multiple Buyers
Real Revenue Example
Timeout Trade-offs
Self-Testing Your Configuration
Monitoring Performance
Optimization Tips
Troubleshooting
FAQ
What's Next
What is Outbound RTB?
Outbound RTB (Real-Time Bidding) allows you to sell calls by auctioning them to multiple buyers in real-time. When you have a call available, you send bid requests to buyers, they respond with offers, and typically the highest bidder wins the call.
You Are the Seller/Publisher
In outbound RTB:
You have calls to sell (from marketing, publishers, campaigns)
You send bid requests to multiple buyers
Buyers respond with how much they'll pay
Highest bidder wins (or you can use other selection criteria)
You earn more than fixed-rate routing by creating buyer competition
Why It's Called "Outbound"
The RTB requests go OUT from your system to buyers. You're sending pings, not receiving them.
When to Use Outbound RTB
Use Outbound RTB When:
✅ You have multiple buyers interested in the same call types (2+ buyers minimum)
✅ You want to maximize revenue by creating buyer competition
✅ Buyer demand fluctuates (some days/times they want more volume)
✅ You want to reduce risk of a single buyer dropping out
✅ You need intelligent routing based on bid price, buyer performance, caps
Skip Outbound RTB When:
❌ You only have 1 buyer (no competition = no auction, just giving them a discount)
❌ Your buyers can't respond quickly (slow responses lose auctions)
❌ Your buyers don't have RTB infrastructure (requires technical capability on their side)
❌ You have exclusive direct deals at higher rates than RTB would generate
Prerequisites
Before setting up outbound RTB, you need:
1. At Least 2 Buyers with RTB Endpoints
Minimum: 2 buyers (for basic competition)
Ideal: 3-5 buyers (for healthy competition)
Diminishing returns: 6+ buyers (good, but latency increases)
💡 Recommendation: Use RTB Groups for parallel bidding. Without RTB Groups, the system checks endpoints sequentially (slower). RTB Groups send bid requests to all buyers simultaneously, improving response time and win rates.
Your buyers must provide:
RTB endpoint URL (e.g., https://api.retreaver.com/rtb/bid)
Authentication (API key, bearer token, etc.) — if required
Request format (which parameters they expect)
Response format (recommended) — Moja's test request will show their actual response, but having their docs helps verify you're mapping correctly
Common Buyer Platforms:
Ringba
Retreaver
TrackDrive
Phonexa
33 Mile Radius
LeadsPedia
Other call tracking platforms with RTB
2. Buyer Data in Moja
Create Buyer records in Moja:
Go to Buyers → Create Buyer
Enter buyer name and contact info
You'll reference these buyers when creating RTB targets
3. Routing Plan to Trigger RTB
Outbound RTB is triggered within a Routing Plan. You need:
A Campaign (call flow is optional)
A Routing Plan where you'll add RTB as a routing destination
💡 Note: You can't hit a destination phone number without a routing plan, regardless of whether you use a call flow.
How Outbound RTB Works
The Flow
Call arrives in your Moja campaign ↓Routing plan evaluates (filters, priority, etc.) ↓RTB Group or RTB Target is selected ↓Moja sends parallel bid requests to all buyers in the group (RTB Groups only - standalone RTB Targets are checked sequentially) ↓Buyers respond with offers (phone number, payout, duration) ↓Moja filters by minimum bid *(RTB Groups only)* and rejects bids exceeding the max bid per target ↓Highest valid bidder wins ↓If winner has "Winning Step", execute it ↓Route call to winning buyer's phone number ↓You get paid the winning bid amount
Key Concepts
RTB Target: A single buyer's endpoint configuration (URL, auth, field mapping)
RTB Group: A collection of RTB Targets that compete in an auction
Set minimum bid (filter out low offers)
Set timeout (how long to wait for responses)
Set maximum bid per target (reject bids exceeding the per-target threshold)
Winning Step: Optional actions to execute AFTER winning (e.g., reserve inventory, confirm booking) — ⚠️ WARNING: Only works inside RTB Groups, FAILS if used standalone
Continue on Failure: Allow RTB to proceed to next step even if one fails (useful for non-critical requests)
Configuration Steps
Overview: Two Paths to RTB
You have two options for implementing outbound RTB:
Option A: RTB Groups (Recommended for Multiple Buyers)
When to use:
You have 2+ buyers
You want parallel bidding (auction format)
You want to set minimum bid thresholds
You need buyer competition to maximize revenue
Steps:
Create RTB Targets for each buyer
Create RTB Group to hold them
Add RTB Group to routing plan
Benefits: Parallel bidding, true auction, highest revenue potential
Option B: Standalone RTB Target (Simple Routing)
When to use:
You have a single buyer
You want simple sequential routing without auction logic
You're testing a new buyer integration
You have specific routing requirements that don't need competition
Steps:
Create RTB Target for buyer
Add RTB Target directly to routing plan
Limitations:
No parallel bidding (sequential only)
No minimum bid filtering
Winning steps won't execute
No auction competition
💡 Recommendation: Even with one buyer initially, consider setting up RTB Groups from the start. It makes adding future buyers easier and enables parallel bidding when you're ready.
Step 1: Create RTB Targets (One Per Buyer)
For each buyer, create an RTB Target:
1.1: Navigate to RTB Targets
Log into Moja
Go to Targets / RTBs → RTBs
Click Create RTB Target
1.2: Basic Configuration
RTB Name: Descriptive name (e.g., "Ringba - Insurance Buyer A")
Buyer: Select from your Buyer records (or create new)
Status: Set to "Active" when ready to use
1.3: Quick Start with Templates (Recommended)
⚠️ BEFORE configuring manually, check if we have a template for your buyer's platform. Templates skip most configuration headaches and avoid the session timeout issue entirely.
See RTB Templates section below for pre-built configurations for:
Ringba
Retreaver
TrackDrive
Phonexa
33 Mile Radius
LeadsPedia
If you find a matching template, load it and skip to Step 1.6 (map your specific credentials). If not, continue with manual configuration below.
1.4: Manual Configuration (Step 1 - Request)
⚠️ CRITICAL SESSION TIMEOUT ISSUE: See Session Timeout Workaround below before proceeding. This is the #1 reason people have trouble configuring RTB.
HTTP Method: Usually GET or POST (check buyer's documentation or template)
Request URL: Buyer's RTB endpoint (e.g., https://api.ringba.com/v2/rtb/bid)
Params Tab (Query Parameters):
Add parameters buyers expect. Common examples:
caller_id = [CALLER_ID] (or test with real number: +16067277702)
zip = [ZIP] or [ZIP_CODE]
state = [STATE]
source = [SOURCE]
campaign_id = [CAMPAIGN_ID]
⚠️ IMPORTANT: When testing/building, use REAL VALUES (see Testing with Static vs Dynamic Values)
[VERIFY NEEDED] Tag case sensitivity: Examples throughout this guide use uppercase tags like [CALLER_ID]. Current documentation warns that tags are case-sensitive, but this has not been independently verified. If you experience issues with tag resolution, verify the exact case requirements with Moja support.
Headers Tab:
Add authentication headers:
Authorization: Bearer YOUR_API_KEY
Or X-API-Key: YOUR_KEY
Body Tab (if POST):
Select body type:
x-www-form-urlencoded (most common)
json (for JSON requests)
form-data (less common)
💡 Note: Most RTB platforms accept parameters either in the request body OR as query parameters. Both methods are valid for key-value pairs. Choose based on your buyer's preference.
Add parameters:
caller_id = +16067277702 (test value)
zip = 90210 (test value)
state = CA
Auth Tab:
Quick authentication setup:
Bearer Token: Paste token
API Key: Choose header or query param, paste key
Basic Auth: Paste base64 credentials
1.5: Test the Request
Click "Send" button to test:
Sends request to buyer's endpoint
Displays response in collapsible panel
Verify you get valid response with phone number, payout, duration
Common Issues:
401 Unauthorized: Check auth credentials
400 Bad Request: Missing required parameters
Timeout: Buyer's endpoint is slow or down
1.6: Map Response Fields
After getting a valid response, map fields:
Phone Number: Select the field containing the routing phone number (e.g., data.phone_number)
Payout: Select the field containing the bid amount (e.g., data.payout or data.bid)
Duration: Select the field containing expected call duration in seconds (e.g., data.duration)
⚠️ CRITICAL: These mappings are REQUIRED. You cannot save without mapping all three (unless using "Use Predefined Phone Number" option).
1.7: Configure Settings
Target Selection: If buyer returns multiple targets, choose how to pick winner:
First (default)
Highest payout
Lowest payout
Highest duration
Lowest duration
Random
Hours of Operation: Set when this buyer accepts calls (default: 24/7)
Timezone: Set timezone for hours interpretation (default: America/New_York)
Max Concurrency: Limit simultaneous calls to this buyer (0 = unlimited)
1.8: Save RTB Target
Click "Save" — your RTB Target is now ready to use in RTB Groups or as a standalone target in routing plans.
Step 2: Create RTB Group (For Multiple Buyers)
Now that you have 2+ RTB Targets, create an RTB Group to auction them:
2.1: Navigate to RTB Groups
Go to Targets / RTBs → RTB groups
Click Create RTB Group
2.2: Basic Information
Group Name: Descriptive name (e.g., "Auto Insurance Buyers - National")
2.3: Bid Settings
Minimum Bid: Lowest bid you'll accept (filters out low offers)
Example: Set to $25.00 to reject any buyer offering less than $25
2.4: Timeout Settings
Ping Timeout (milliseconds):
How long to wait for each buyer to respond before timing out.
Default: 2000ms (2 seconds) — Recommended for most use cases
Maximum: 10000ms (10 seconds)
Trade-offs: See Timeout Trade-offs section
2.5: Select RTB Targets
Add your RTB Targets to the group:
Click "Add RTB Target"
Select from dropdown (e.g., "Ringba - Buyer A", "Retreaver - Buyer B")
Repeat for all buyers
2.6: Set Maximum Bid Per Target (Optional)
For each RTB Target in the group, you can set a maximum acceptable bid:
Example:
Track Drive - Buyer A: Max bid $50.00
Retreaver - Buyer B: Max bid $45.00
Purpose:
Protect against runaway or erroneous bids (e.g., a buyer accidentally submitting $10,000 instead of $100)
Enforce negotiated rate ceilings by rejecting bids above the agreed threshold
Test new buyers by limiting which bids are accepted into the auction
How it works:
Max bid is a bid rejection filter — not a payout cap. Any incoming bid that exceeds the max bid value is rejected outright and does not enter the auction. The bid is discarded entirely; it does not get reduced or capped to the threshold.
Important: Max bid does NOT affect payouts. If a bid is accepted (i.e., it is at or below the max bid), the winner is paid their actual winning bid amount. Max bid only controls which bids are allowed to compete.
Max Bid Setting | Incoming Bid | Result |
$50 | $35 | ✅ Accepted — enters auction |
$50 | $50 | ✅ Accepted — at threshold |
$50 | $60 | ❌ Rejected — exceeds max bid |
$50 | $10,000 | ❌ Rejected — clearly erroneous |
2.7: Save RTB Group
Click "Save" — your RTB Group is ready to use in Routing Plans.
Step 3: Add RTB to Routing Plan
Now add your RTB Group (or standalone RTB Target) to a campaign's routing plan:
3.1: Navigate to Campaign Settings
Go to Campaigns → Select campaign
Click Settings → Routing Plans
Select a routing plan or create new
3.2: Add Route
Click "Add Route"
Action: Select "Route to RTB Group" (recommended) or "Route to RTB Target" (for standalone)
RTB Group/Target: Select from dropdown
Priority: Set priority (lower number = higher priority)
3.3: Save Routing Plan
Click "Save" — your RTB configuration is now live and will start auctioning calls.
RTB Templates (Quick Start)
The fastest way to configure outbound RTB is to use pre-built templates for common buyer platforms. Templates handle all the technical details (HTTP method, URL structure, parameter mapping) so you only need to provide your credentials.
Available Templates
Template 1: Ringba - Standard RTB
Platform: Ringba
Use Case: Standard real-time bidding for call routing
Method: GET (99% of Ringba RTB implementations use GET)
Configuration
HTTP Method: GET
Request URL:
https://rtb.ringba.com/v1/production/#{{RINGBA_UUID}}.json
Query Parameters:
CID=[CALLER_ID]zipcode=[ZIP_CODE]exposeCallerID=yes
Placeholders to Replace:
#{{RINGBA_UUID}}- Your 32-character hex UUID from Ringba campaign (e.g.,a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6)
Response Mapping:
Phone Number:
phoneNumberPayout:
bidAmountDuration:
bidTerms[0].callMinDuration
Timeout: 10000ms (10 seconds)
Notes:
Ringba requires caller ID for most buyers
ZIP code is typically required but varies by vertical
exposeCallerID=yesensures caller ID is passed through to buyer
Template 2: Retreaver - Standard RTB
Platform: Retreaver
Use Case: Standard RTB integration
Method: POST
Configuration
HTTP Method: POST
Request URL:
https://rtb.retreaver.com/rtbs.json?key=#{{RETREAVER_KEY}}
Query Parameters (REQUIRED for key):
key=#{{RETREAVER_KEY}}
💡 CRITICAL: The API key MUST go in query parameters (this is non-negotiable with Retreaver). Other fields can go in parameters OR body.
Body (JSON):
{ "publisher_id": "#{{PUBLISHER_ID}}", "caller_number": "[CALLER_ID]", "caller_zip": "[ZIP_CODE]"}
Placeholders to Replace:
#{{RETREAVER_KEY}}- Your Retreaver API key#{{PUBLISHER_ID}}- Your publisher ID in Retreaver's system
Response Mapping:
Phone Number:
inbound_numberPayout:
retreaver_payoutDuration:
retreaver_seconds
Timeout: 10000ms (10 seconds)
Template 3: TrackDrive - Standard Ping
Platform: TrackDrive
Use Case: Ping-based call routing with predefined numbers
Method: POST
Configuration
HTTP Method: POST
Request URL:
https://#{{TRACKDRIVE_SUBDOMAIN}}.trackdrive.com/api/v1/inbound_webhooks/ping/#{{TRACKDRIVE_ENDPOINT}}
Query Parameters (REQUIRED):
trackdrive_number=#{{TRACKDRIVE_NUMBER}}traffic_source_id=#{{TRAFFIC_SOURCE_ID}}
Body (JSON):
{ "caller_id": "[CALLER_ID]", "zip": "[ZIP_CODE]"}
Placeholders to Replace:
#{{TRACKDRIVE_SUBDOMAIN}}- Your TrackDrive account subdomain#{{TRACKDRIVE_ENDPOINT}}- Your ping endpoint ID#{{TRACKDRIVE_NUMBER}}- Your predefined tracking phone number#{{TRAFFIC_SOURCE_ID}}- Your traffic source identifier
Response Mapping:
Phone Number: NOT MAPPED (use predefined)
Payout:
buyers[0].offer_conversion_payoutDuration:
buyers[0].current_conversion_duration
Special Configuration:
✅ Enable "Use Predefined Phone Number"
Phone Number:
#{{TRACKDRIVE_NUMBER}}(same as parameter above)
⚠️ CRITICAL: TrackDrive ALWAYS uses a predefined phone number. The phone number serves as both a field value in the request AND the DID (destination) for routing. Do NOT attempt to map a phone number from TrackDrive's response.
Timeout: 10000ms (10 seconds)
Template 4: Phonexa - Store SetData
Platform: Phonexa
Use Case: Call tracking with setData API
Method: POST
Configuration
HTTP Method: POST
Request URL:
https://#{{PHONEXA_SUBDOMAIN}}.phonexa.com/store/setdata
Body (JSON):
{ "apiId": "#{{API_ID}}", "apiPassword": "#{{API_PASSWORD}}", "productId": "#{{PRODUCT_ID}}", "clientNumber": "[CALLER_ID]", "centerCode": "#{{CENTER_CODE}}", "zipCode": "[ZIP_CODE]"}
Placeholders to Replace:
#{{PHONEXA_SUBDOMAIN}}- Your Phonexa account subdomain#{{API_ID}}- Your Phonexa API ID#{{API_PASSWORD}}- Your Phonexa API password#{{PRODUCT_ID}}- Target product/campaign ID#{{CENTER_CODE}}- Your center/location code
Response Mapping:
Phone Number:
data.phoneNumberPayout:
data.priceDuration:
data.callMinDuration
Timeout: 10000ms (10 seconds)
Template 5: 33 Mile Radius - Standard RTB
Platform: 33 Mile Radius
Use Case: Geographic-based call routing
Method: GET
Configuration
HTTP Method: GET
Request URL:
https://calls.33mileradius.com/api/v3/
Query Parameters:
password=#{{33MILE_PASSWORD}}zip=[ZIP_CODE]duration=1
Placeholders to Replace:
#{{33MILE_PASSWORD}}- Your 33 Mile Radius API password
Response Mapping:
Phone Number: NOT MAPPED (use predefined)
Payout:
amountDuration:
duration
Special Configuration:
✅ Enable "Use Predefined Phone Number"
Phone Number: (Provided by 33 Mile Radius - contact your account manager)
⚠️ CRITICAL: Like TrackDrive, 33 Mile Radius uses predefined phone numbers. You must obtain the routing number from 33 Mile Radius and configure it as a static value.
Timeout: 10000ms (10 seconds)
Template 6: LeadsPedia - Standard Ping
Platform: LeadsPedia
Use Case: Lead verification and call routing
Method: GET
Note: This template is sourced from internal PR #339 and may not have been discussed in training materials. Verify with your LeadsPedia account manager before use.
Configuration
HTTP Method: GET
Request URL:
https://#{{LEADSPEDIA_SUBDOMAIN}}.leadspediatrack.com/call-preping.do
Query Parameters:
lp_campaign_id=#{{CAMPAIGN_ID}}lp_campaign_key=#{{CAMPAIGN_KEY}}caller_id=[CALLER_ID]zip_code=[ZIP_CODE]
Placeholders to Replace:
#{{LEADSPEDIA_SUBDOMAIN}}- Your LeadsPedia account subdomain#{{CAMPAIGN_ID}}- Your LeadsPedia campaign ID#{{CAMPAIGN_KEY}}- Your LeadsPedia campaign key
Response Mapping:
Phone Number:
numberPayout:
payoutDuration:
duration
Timeout: 10000ms (10 seconds)
How to Use Templates
Step 1: Load Template
When creating a new RTB Target, look for "Load Template" option
Select your buyer's platform from the dropdown
Template auto-populates method, URL structure, parameters, and response mappings
Step 2: Fill in Your Credentials
Replace all #{{PLACEHOLDER}} values with your actual credentials:
API keys
Account IDs
Subdomain names
Campaign identifiers
Step 3: Test Request
For testing, replace
[CALLER_ID]and[ZIP_CODE]with real values:Example:
caller_id = +16067277702Example:
zip = 90210
Click "Send" to test the request
Verify you receive a valid response
Step 4: Restore Dynamic Tags
After successful testing, restore the dynamic tags:
Replace test phone number with
[CALLER_ID]Replace test zip with
[ZIP_CODE]
Step 5: Save
Click "Save" — your template-based RTB Target is ready to use!
Template Benefits
✅ Faster setup - Skip manual URL/parameter configuration
✅ Fewer errors - Pre-validated configurations reduce mistakes
✅ Avoid session timeout - Templates load instantly, no timeout risk
✅ Industry best practices - Based on real production integrations
✅ Regular updates - Templates maintained as platforms evolve
💡 Tip: Even if you're an experienced RTB user, templates save time and ensure you're using the latest recommended configuration for each platform.
Session Timeout Workaround
The Problem
This is the #1 UX issue when configuring outbound RTB manually (templates avoid this entirely):
When you're building an RTB Target from scratch, there's a high chance you'll encounter a session timeout before completing configuration. This happens because:
You're filling in URL, params, headers, body
Testing the request (may take time to get buyer's endpoint right)
Mapping response fields
Configuring settings
Even experienced users get kicked out often. Until you have a response mapped, you cannot save the RTB Target.
Recommended Solutions
Solution 1: Use RTB Templates (Best Option)
Templates are pre-configured and load instantly, eliminating the timeout issue entirely. See RTB Templates section above.
Solution 2: Map Fake Fields Quickly (Manual Workaround)
If building manually, do this as FAST as possible:
Put ANY values in URL and required fields
Click "Send" to get ANY response (even an error response)
Once you have a response, map fields to ANYTHING:
Map a random field to "Phone Number"
Map a random field to "Payout"
Map a random field to "Duration"
Select a Buyer (required)
Click "Save" immediately
NOW go back and configure it properly:
Fix the URL
Fix params/headers/body
Re-test to get real response
Re-map fields correctly
Save again
Why this works: You get past the "cannot save without mapping" barrier before session timeout.
Solution 3: Load Sample Response
If your buyer gave you sample response JSON:
Configure URL, params, headers, body (don't test yet)
Click "Load Sample Response" button
Paste the sample JSON your buyer provided
Map fields from the sample
Select a Buyer
Click "Save" immediately
NOW test with real request and verify mappings
Solution 4: Work in Text Editor First
If you're dealing with complex configurations:
Draft your configuration in a text editor:
List all params with values
List all headers
Draft body JSON
Copy-paste into Moja quickly
Load sample response or test quickly
Map and save ASAP
Long-Term Fix Needed
We've escalated this to product team. Future improvements may include:
"Are you still working on this?" prompt
Auto-save draft configurations
Longer session timeout for RTB config page
Testing with Static vs Dynamic Values
The Confusion
When building RTB, you configure fields using tags like [CALLER_ID], [ZIP], [STATE].
❓ Question: During testing, should you use the literal tags [CALLER_ID] or actual values like +16067277702?
The Answer: Use Actual Values When Testing
❌ WRONG (during testing):
caller_id: [CALLER_ID]zip: [ZIP_CODE]
✅ CORRECT (during testing):
caller_id: +16067277702zip: 90210
Why?
When you click "Send" to test your configuration:
Moja sends the literal content of the fields
If you have [CALLER_ID], Moja sends the string "[CALLER_ID]" (not a real phone number)
Your buyer receives an incomplete request and returns an error
You can't map response fields without a valid response
During live execution (real calls), Moja replaces tags with actual values:
[CALLER_ID] → +16067277702
[ZIP] → 90210
[STATE] → CA
Testing Flow
Step 1: Test with Static Values
Put real values in fields:
caller_id = +16067277702 (real phone number)
zip = 90210
state = CA
Click "Send" → Get valid response → Map fields → Save
Step 2: Replace with Dynamic Tags
After saving, go back and replace with tags:
caller_id = [CALLER_ID]
zip = [ZIP_CODE]
state = [STATE]
Save again.
Step 3: Test with Real Call
Send a test call through your campaign to verify tags are replaced correctly.
Platform-Specific Configuration
The RTB Templates section above provides detailed configurations for major platforms. This section covers additional platform-specific notes and edge cases.
General Caller ID Requirements
⚠️ CRITICAL: Caller ID is essential for RTB - 90% of buyers require it.
Without caller ID:
Most buyers will reject your bid requests
You'll see low fill rates and poor performance
Calls won't pair with RTB buyers effectively
How caller ID is resolved:
Caller ID present: Use it directly
No caller ID but have phone number: Attempt automatic lookup
Neither available: Bid requests likely to fail
💡 Best Practice: Always ensure caller ID is captured and passed through your call flow before RTB routing.
NPANXX Lookup (Automatic)
If caller ID is present but ZIP code or state are missing, Moja automatically performs an NPANXX lookup to populate geographic data.
You do NOT need to configure this - it happens automatically.
How it works:
System extracts area code and exchange from caller ID
Looks up geographic location in NPANXX database
Populates [ZIP_CODE] and [STATE] tags automatically
This data is then available for RTB requests
Platform Notes
Ringba:
99% of implementations use GET method (not POST)
Requires UUID in URL path
Most buyers require caller ID and zip code
Response format is consistent and well-documented
Retreaver:
API key MUST be in query parameters (non-negotiable)
Other fields can be in query params OR body (both valid)
Supports both JSON and form-encoded bodies
TrackDrive:
ALWAYS uses predefined phone numbers
Phone number serves as both field value and routing destination
All required fields must be sent as parameters
Subdomain and endpoint ID are account-specific
Phonexa:
Uses POST with JSON body
Requires API credentials in every request
Response includes detailed call handling parameters
Center code is location-specific
33 Mile Radius:
Geographic-focused routing
Predefined phone numbers (like TrackDrive)
Requires password authentication in query params
Duration parameter typically set to 1
LeadsPedia:
Campaign-based routing
GET method with query parameters
Both campaign ID and key required
Verify integration with account manager before use
Lead Protection (Multi-Step RTB)
The Problem
In standard RTB, you send caller data (phone number, zip, state) to buyers during the bid request. A bad actor could:
Log your caller data without ever winning calls
Cherry-pick your best leads
Steal your lead data to contact directly
The Solution: Multi-Step RTB
Moja supports multi-step RTB to protect your leads:
Step | What's Shared | Buyer Action |
Step 1: Ping | Anonymous data only (time, vertical, general geo) | Buyer indicates interest + max bid |
Step 2: Post | Full caller data (only to winner) | Winner confirms acceptance |
Step 3: Transfer | Call connected | Buyer receives call and pays |
How to Configure Multi-Step RTB
Step 1: Ping (Anonymous)
Configure a request with minimal data:
Params:
state: [STATE] (broad geo)
vertical: auto_insurance
timestamp: [TIMESTAMP]
NO caller_id or zip in this step.
Response Mapping:
Map buyer's interest indicator (e.g., interested: true)
Step 2: Add Next Step (Post Winner)
Click "Add Step"
Configure Step 2:
URL: Buyer's "post" endpoint (e.g., https://api.buyer.com/rtb/confirm)
Params: Include full data:
caller_id: [CALLER_ID]
zip: [ZIP_CODE]
ping_id: [PREVIOUS_STEP_PING_ID] (custom variable from Step 1)
Important: Step 2 only executes for the WINNING buyer of an RTB Group.
Step 3: Map Variables Between Steps
To pass data from Step 1 to Step 2:
In Step 2, scroll to "Previous Steps Mapping"
Click "Add Variable Mapping"
Select:
Source Step: Step 1
Field: data.ping_id
Tag Name: PING_ID
Now you can use [PING_ID] in Step 2 params/headers/body
Example:
Step 1 returns:
{ "data": { "ping_id": "abc123", "bid": 45.00 } }Map PING_ID → Step 1 → data.ping_id
Step 2 uses: ping_id: [PING_ID] → Resolves to ping_id: abc123
Lead Protection Best Practices
Minimize data in initial ping:
Send state, NOT zip
Send time/day, NOT caller ID
Vet buyers before sharing full data:
Start with ping-only relationships
Graduate to full data after trust is established
Use contracts/NDAs
Monitor for data leakage:
Track if buyers are contacting your leads directly
Watch for suspicious patterns (buyer bids but never wins)
Rotate test caller IDs to detect harvesting
Why You Need Multiple Buyers
1 Buyer = Discount, Not Auction
The Math:
Buyers | What Happens | Your Revenue |
1 buyer | No competition → they bid minimum | ❌ $25/call (floor price) |
2 buyers | Basic competition | ✅ $35/call (20% increase) |
3-5 buyers | Healthy competition | ✅ $40-50/call (competitive market price) |
6+ buyers | Diminishing returns | ⚠️ $50-55/call (marginal gains, increased latency) |
Key insight: If you only have 1 buyer, you're not running an auction. You're just routing to them at whatever rate they decide to bid (usually minimum).
Why Buyers Bid Low with No Competition
When a buyer knows they're the only option:
They have no incentive to bid high
They'll bid just enough to meet your minimum
They'll test lowering bids to see if you'll still route
Real example:
Single buyer setup: Buyer bids $25 consistently
After adding 2nd buyer: First buyer raises bids to $35-40 to avoid losing calls
How to Add More Buyers
Option 1: Existing Relationships
Ask buyers you already work with:
"Do you have an RTB endpoint? We're implementing real-time bidding to optimize our routing. What's your API documentation?"
Option 2: Call Marketplaces
Join call trading platforms where buyers congregate:
Vertical-specific call marketplaces
Industry networks (e.g., insurance lead buyer groups)
Option 3: Competitor's Buyers
If you are losing to competitors:
Offer competitive rates
Highlight your call quality/volume
Goal: Aim for 3-5 active buyers in each RTB Group for optimal competition.
Real Revenue Example
Case Study: Home Services Publisher
Before RTB (Direct Routing):
Metric | Value |
Routing method | Direct to single buyer |
Fixed rate | $35/call |
Monthly calls | 2,400 |
Monthly revenue | $84,000 |
Fill rate | 100% (buyer accepts all calls) |
After RTB (+3 Buyers):
Metric | Value |
Routing method | RTB Group with 4 buyers |
Average winning bid | $47/call |
Monthly calls | 2,400 |
Monthly revenue | $112,800 |
Fill rate | 94% (some calls don't meet any buyer's filters) |
Calls to fallback | 144 (6% routed to original buyer at $25/call) |
Calculation:
2,256 calls via RTB × $47 = $106,032
144 calls to fallback × $25 = $3,600
Fallback + RTB revenue = $109,632
Plus 144 calls at original $35 rate would've been $5,040
Net difference: $112,800 - $84,000 = +$28,800/month (+34% revenue increase)
Key Insight:
Even with slightly lower fill rate (94% vs 100%), total revenue increased significantly due to higher per-call payouts from competitive bidding.
Factors in Success
Buyer competition: 4 buyers competing drove bids up
Dynamic market pricing: Different buyers valued calls differently based on capacity/need
Fallback routing: Unsold calls still monetized at lower rate
Quality filtering: Some low-quality calls excluded, improving overall mix
Timeout Trade-offs
Choosing Your Auction Timeout
The "Ping Timeout" in your RTB Group controls how long to wait for buyers to respond.
Timeout | Pros | Cons | Best For |
2 seconds | Fast caller experience, quick auctions | May exclude slow-but-high-bidding buyers | High-volume, price-sensitive, general leads |
5 seconds | More buyers can participate, higher potential bids | Caller waits longer (slight hangup risk) | Premium leads, max revenue focus |
10 seconds | Maximum competition, all buyers included | Poor caller experience, higher hangup risk | Very high-value calls only (e.g., $100+ leads) |
Our Recommendation
Start with 2 seconds. This is optimal for most publishers because:
Caller experience matters: Every second of silence before connection increases hangup risk
Fast buyers win: Buyers who respond quickly are usually better organized/more serious
ROI trade-off: Revenue from faster connections often outweighs revenue from slower, higher bids
When to Increase Timeout
Scenario: You have a buyer who consistently bids high but is slow to respond.
Options:
Increase timeout to 5s:
Monitor hangup rate (acceptable increase: <5%)
Track revenue gain from slow buyer
If gain > loss from hangups, keep it
Talk to the buyer:
Ask if they can speed up their endpoint
Offer to help optimize their integration
Some buyers can improve response time when asked
Set a floor bid:
If their bids are consistently above your floor, consider direct routing to them for certain calls
Create separate routing rule: "High-value calls → Slow Buyer directly (bypass RTB)"
Monitoring Timeout Impact
Track these metrics per timeout setting:
Metric | What It Tells You |
Average response time | How fast buyers are responding |
Timeout rate per buyer | % of requests each buyer times out on |
Revenue per call | Is longer timeout generating higher bids? |
Self-Testing Your Configuration
How to Test Without a Real Call
You can simulate an inbound RTB request to test your outbound RTB configuration:
Method: Use Your Inbound RTB URL
Go to Campaign Settings → Inbound RTB Configuration
Copy your inbound RTB endpoint URL:
https://rtb.moja.cloud/inbound_rtb/inbound_rtb_abc123xyz
Append test parameters (using query string):
https://rtb.moja.cloud/inbound_rtb/inbound_rtb_abc123xyz?CALLER_ID=+16067277702&CALLER_ZIP=90210&CALLER_STATE=CA
Use the full endpoint URL, including https://. Replace the sample caller ID value with the caller ID value or variable from the sending platform.
Open this URL in your browser
What happens:
Moja receives the request as if from a publisher
Your outbound RTB fires (sends requests to buyers)
Buyers respond with bids
Moja selects winner and returns response
Browser displays the response JSON
Example Response:
{ "success": true, "request_id": "3151f96b-41f7-48af-87eb-0399b1a6135d", "inbound_rtb_id": "inbound_rtb_17604732101070_7b47mu", "allocation_time_seconds": 30, "eligible_routes": [ { "number": "+17015525707", "payout": 72, "duration": 60 } ], "total_routes": 1, "allocated_count": 1, "timestamp": "2026-02-03T16:34:22.572Z"}
Interpreting Results
✅ Success Indicators:
Response returned (not timeout)
bid field present with expected value
phone_number field present and valid
Response time < 2 seconds
❌ Problem Indicators:
Timeout (no response after 10+ seconds) → Check buyer endpoints
error field present → Read error message
Total_routes: 0 → Buyers rejected or no eligible buyers
Monitoring Performance
Where to Check Performance
Location: Go to Reporting → RTB Requests → Outbound
Key Metrics to Monitor
1. Bid Request Volume
What it shows: How many auctions you're running
Where: RTB Requests → Outbound → "Total Requests" column
Good: Matches your call volume
Bad: Lower than call volume (RTB not triggering for some calls)
2. Response Rate Per Buyer
What it shows: Percentage of requests each buyer responded to
Where: RTB Requests → Outbound → Filter by buyer → "Response Rate" column
Good: > 90% per buyer
Bad: < 10% (buyer's endpoint is slow or unreliable, varies by vertical)
💡 Note: Win rate thresholds vary significantly by vertical. In some industries, 90% win rate indicates excellent performance, while under 10% suggests problems. Evaluate your specific market conditions when interpreting these metrics.
3. Average Winning Bid
What it shows: Average payout you're earning per call
Where: RTB Requests → Outbound → "Avg Winning Bid" column
Monitor: Track trends over time
Action: If declining, investigate why (more competition among buyers? quality issues?)
4. Win Rate Per Buyer
What it shows: Which buyers win most often
Where: RTB Requests → Outbound → "Win Rate by Buyer" breakdown
Insights:
If one buyer wins 80%+ → They're overbidding OR others are underdelivering
If spread evenly → Healthy competition
If one buyer never wins → They're not competitive or have technical issues
5. Timeout Rate Per Buyer
What it shows: Percentage of times each buyer times out
Where: RTB Requests → Outbound → "Timeout Rate" column (per buyer)
Good: < 5%
Bad: > 10% (buyer's endpoint is slow; consider longer timeout or removing slow buyers)
Call-level RTB troubleshooting
For a specific call, open Reporting / Call Logs, select the call, then open the call details panel.
Use Call Life to see RTB activity grouped into readable cards inside the full call timeline.
Use the RTB tab to focus only on RTB activity for that call.
Expand RTB cards or step rows to review request/response details, winner details, no-bid outcomes, below-minimum bids, errors, or timeouts when available.
For RTB Groups, the card view can show participant-level outcomes so you can see which formulas responded, which one won, and which attempts failed or timed out.
Optimization Tips
1. Monitor Buyer Performance
Track each buyer separately:
Response rate (reliability)
Win rate (competitiveness)
Average bid (pricing)
Call duration (quality indicator)
Conversion rate (if you have downstream data)
Action: If a buyer consistently underperforms:
Raise their max bid threshold (so more of their bids are accepted into the auction)
Or remove them from the group
Or move them to a lower-priority group
2. Segment RTB Groups by Buyer Quality
Create separate RTB Groups for different quality tiers:
Example:
Group 1: Premium Leads
Filters: CA, TX, FL, NY only + business hours
Minimum Bid: $40
Buyers: Your highest-paying buyers (3-4 buyers)
Group 2: Standard Leads
Filters: 20 states, extended hours
Minimum Bid: $25
Buyers: Mid-tier buyers (4-5 buyers)
Group 3: Filler Leads
Filters: National, 24/7
Minimum Bid: $15
Buyers: Volume buyers willing to take anything (2-3 buyers)
Routing Plan Priority:
Premium Group (try first)
Standard Group (if premium rejects or doesn't meet minimum)
Filler Group (last resort)
Static fallback target (if all RTB fails)
3. Dynamic Floor Pricing
Adjust minimum bid based on call characteristics:
Example:
High-value geos (CA): Minimum bid $40
Medium-value geos (TX, FL): Minimum bid $30
Low-value geos (all others): Minimum bid $20
How to implement:
Create separate RTB Groups per geo tier
Group similar buyer coverage areas
Set different minimum bids per group
4. Test New Buyers Safely
When adding a new buyer, protect your revenue:
Create test RTB Group:
Include new buyer + 1-2 proven buyers
Set a minimum bid floor
Low volume initially (10-20 calls/day)
Monitor for 1 week:
Response rate
Win rate
Call acceptance (do calls connect?)
Buyer feedback (quality complaints?)
Graduate or remove:
If performing well, increase cap and volume
If underperforming, remove or adjust
5. Geographic Routing via Multiple Groups
While Moja doesn't have a built-in "geographic routing" feature per se, you can achieve geo-specific buyer routing by creating multiple RTB Groups with different geographic filters:
Example Setup:
Group A: West Coast Buyers
Filter: CA, OR, WA only
Buyers: West-coast-focused buyers who pay premium for these states
Group B: East Coast Buyers
Filter: NY, NJ, MA, FL
Buyers: East-coast-focused buyers
Group C: National Buyers
Filter: All states
Buyers: National buyers (lower bids but broader coverage)
Routing Priority:
Check regional group first (if call matches geo)
Fall back to national group if no winner
This approach allows you to optimize routing based on buyer geographic preferences without requiring special platform features.
Troubleshooting
Problem: Buyers Not Responding
Possible Causes:
Buyer's endpoint is down or slow
Your request format is incorrect
Authentication is wrong
Timeout is too short
How to Fix:
Test buyer endpoint directly:
Go to RTB Target config
Click "Send" to test
Check response or error
Check buyer's status:
Contact buyer to verify endpoint is operational
Ask if they're seeing your requests in their logs
Verify authentication:
Re-check API key or bearer token
Test with buyer's example credentials (if they provided)
Increase timeout:
If buyer is consistently slow, increase RTB Group timeout to 5s
Monitor if this impacts caller experience
Problem: All Buyers Rejecting Calls (No Winner)
Possible Causes:
Missing required fields (caller ID, zip)
Calls don't meet buyers' filters (wrong state, time, quality)
Buyers at capacity (max concurrency reached)
Your minimum bid is too high
How to Fix:
Check required fields:
Verify caller ID is being sent: [CALLER_ID] tag
Verify zip is being sent: [ZIP_CODE] tag
Test with real values to ensure tags are resolving
Review buyer filters:
Ask buyers what filters they have
Check if your calls match their criteria
Check buyer capacity:
Ask buyers if they're at concurrency limits
Consider adding more buyers
Lower minimum bid:
Test with minimum bid = $0 to see if you get any bids
Gradually raise until you find market-clearing price
Problem: Winner Selected But Call Doesn't Connect
Possible Causes:
Phone number mapping is wrong
Winning phone number is invalid or disconnected
Caller hung up before connection
Buyer's phone system is down
How to Fix:
Verify phone number mapping:
Go to RTB Target config
Check "Phone Number" mapping is correct field
Test and verify response contains valid phone number
Test winning phone number directly:
Call the number manually to verify it works
If disconnected, contact buyer
Check call logs:
Go to Call Logs → filter by campaign
Look for connection status
Check for errors or call failure reasons
Contact buyer:
Report specific call with UID
Ask if they received the call attempt
Investigate their system status
Problem: Session Timeout During Configuration
Cause: You're getting kicked out before completing RTB Target setup.
How to Fix:
Best Solution: Use RTB Templates (see RTB Templates section) - templates load instantly and eliminate timeout issues.
Alternative: See Session Timeout Workaround section above.
TL;DR: Map ANY fields quickly, save immediately, THEN configure properly.
Problem: Tags Not Resolving (Seeing Literal [CALLER_ID])
Possible Causes:
You're testing from configuration page (expected behavior)
Caller ID is not available in call flow
Tag name is misspelled
How to Fix:
If testing from config page:
This is normal (see Testing with Static vs Dynamic Values)
Use real values for testing, tags for live
If in live call:
Check call logs: Does call have caller ID?
[VERIFY NEEDED] Tag case sensitivity: Current documentation warns tags are case-sensitive (e.g.,
[CALLER_ID]not[caller_id]), but this has not been independently verified. If experiencing issues, contact Moja support to confirm exact case requirements.Check if NPANXX lookup succeeded (needed for [ZIP], [STATE])
Problem: Winning Step Fails
Cause: You configured a "Winning Step" but it's failing or not executing.
⚠️ CRITICAL GOTCHA: Winning Steps ONLY work inside RTB Groups. If you use an RTB Target with a winning step as a standalone target in routing plan, IT WILL FAIL.
How to Fix:
Verify the RTB Target is inside an RTB Group
Do NOT use winning step RTB Targets as standalone routing targets
Winning step only executes after RTB Group selects this target as winner
Example:
Step 1: Send bid request
Buyer responds with bid
Moja selects this buyer as winner
Step 2 (Winning Step): POST to buyer's confirm endpoint with booking details
FAQ
Q: What's the difference between RTB Target and RTB Group?
A:
RTB Target: Configuration for a single buyer's endpoint
One buyer
One endpoint URL
Request/response mappings
Can be used standalone or in groups
RTB Group: Collection of RTB Targets that compete in auction
Multiple RTB Targets (buyers)
Minimum bid setting
Timeout setting
Maximum Bid Per Target caps
Analogy: RTB Targets are players. RTB Groups are teams. You need both (or just a standalone target for single-buyer scenarios).
Q: Can I use the same RTB Target in multiple RTB Groups?
A: Yes! This is common and recommended.
Example:
Premium Group: Buyer1 + Buyer2 + Buyer3 (minimum bid $40)
Standard Group: Buyer1 + Buyer2 + Buyer4 (minimum bid $25)
Same RTB Targets, different groups with different settings.
Q: What happens if no buyer meets the minimum bid?
A: Moja responds with "no bid" and the call proceeds to the next route in your routing plan.
Recommended Setup:
Routing Plan:
Priority 1: RTB Group (minimum $40) → Try premium buyers first
Priority 2: RTB Group (minimum $25) → Try standard buyers if premium fails
Priority 3: Static Target ($20 fixed) → Fallback to guaranteed buyer
This ensures every call is monetized, even if RTB doesn't produce a winner.
Q: How do I prevent the same buyer from winning every time?
A: Max bid is a bid rejection filter, not a tool for balancing winner distribution. Setting a max bid on Buyer A will cause any of their bids that exceed the threshold to be rejected entirely — Buyer A simply won't participate in those auctions.
Example of what max bid does and doesn't do:
Without max bid:
Buyer A always bids $60
Buyer B always bids $50
Buyer A wins 100% of calls (highest valid bid wins)
With max bid (Buyer A max bid = $55):
Buyer A bids $60 → ❌ Rejected (exceeds $55 max bid) — Buyer A does not compete
Buyer B bids $50 → ✅ Accepted — Buyer B wins at $50
⚠️ Note: Max bid does not cap Buyer A's payout at $55 — it rejects the bid outright. If you want to prevent one buyer from dominating without excluding them, use concurrency caps or routing plan priority instead (see Advanced Caps section).
Advanced: Rotate winners manually:
Create multiple RTB Groups with different buyer combinations
Rotate which group is used based on call volume, time, or randomly
Q: Can I offer the same call to multiple RTB Groups sequentially?
A: Yes! Use routing plan priority.
Example:
Routing Plan:
Priority 1: Premium RTB Group (minimum $50, 3 buyers)
If no winner, proceed to Priority 2
Priority 2: Standard RTB Group (minimum $30, 5 buyers)
If no winner, proceed to Priority 3
Priority 3: Filler RTB Group (minimum $15, 2 buyers)
How it works:
Call tries Premium first
If no buyer bids >= $50, moves to Standard
If no buyer bids >= $30, moves to Filler
If still no winner, falls back to static target (if configured)
Q: How do I test RTB without impacting live calls?
A: Create a test campaign:
Create Test Campaign:
Go to Campaigns → Create Campaign
Name: "RTB Test Campaign"
Use test phone number (assign dedicated number)
Configure Test RTB:
Create RTB Targets in test mode
Create test RTB Group
Add to test campaign's routing plan
Send Test Calls:
Call your test number
Verify routing, bidding, connections
Monitor logs for errors
Graduate to Production:
Once satisfied, copy configuration to production campaign
Or migrate test campaign to production status
Q: What's "Continue on Failure" and when should I use it?
A: "Continue on Failure" allows a multi-step RTB to proceed to the next step even if the current step fails.
Use cases:
Scenario 1: Non-Critical Data Collection
Step 1: Send bid request → Get phone number, payout, duration
Step 2: Send analytics ping to your tracking system (informational only)
Enable "Continue on Failure" on Step 2
If your tracking system is down, call still connects (Step 2 failure doesn't block routing)
Scenario 2: Optional Enhancements
Step 1: Primary bid request
Step 2: Fetch additional caller data from 3rd party API
Enable "Continue on Failure"
If 3rd party is slow/down, call proceeds without enhanced data
When NOT to use:
Critical steps (if Step 1 bid request fails, you want to KNOW and not proceed)
What's Next
Once you've mastered outbound RTB basics, explore these advanced topics and resources:
1. Review Your RTB Performance
Go to Reporting → RTB Requests → Outbound to monitor:
Bid request volume and trends
Response rates per buyer
Average winning bids over time
Win rate distribution across buyers
Fill rate and timeout metrics
Use these insights to optimize your RTB Groups, adjust minimum bids, and identify underperforming buyers.
2. Multi-Step RTB Workflows
Chain multiple requests for complex buyer integrations:
Ping → Post → Confirm
Bid → Book → Transfer
Qualify → Price → Route
Use Case: Buyers who require multi-stage approval (ping for eligibility, post for booking)
How: Use "Previous Steps Mapping" in step configuration to pass data between steps (see Lead Protection section)
3. Custom Tags and Variables
Pass data between steps using custom tags:
Extract session token from Step 1, use in Step 2
Pass ping ID from initial request to confirmation request
Use buyer's reference ID in subsequent steps
How: Configure "Previous Steps Mapping" to create custom tags from earlier response fields
4. Advanced Caps and Budgets
Protect against overspending with advanced cap features:
Daily revenue caps per buyer
Hourly call limits per buyer
Rolling 24-hour caps
Custom time-window caps (e.g., "100 calls per 6-hour window")
How: Go to RTB Target → Advanced Caps section
For Inbound RTB traffic routed through RTB Groups, advanced caps count against the winning RTB formula when a winner is selected. This helps cap tracking reflect the actual source that received the billable call instead of a generic Inbound RTB label.
Need Help?
Documentation
Inbound RTB Guide: Learn how to buy calls via RTB
Webhooks Guide: Push call data to external systems in real-time
Support
Email: [email protected]
Live Chat: Available in the Moja dashboard
Version: 4.1
Last Updated: April 21, 2026
Feedback: [email protected]