Skip to main content

Inbound Webhooks Guide

D
Written by Denise Abdullah
Updated over a month ago

Inbound Webhooks Guide


Overview

Inbound webhooks allow you to send data to MojaAI from your systems. Use these webhooks to pass caller metadata before a call is routed, update revenue on completed calls, or manage custom tags for reporting and attribution.

What you can do with inbound webhooks:

  • Pass caller metadata during call routing (e.g., lead source, campaign data)

  • Update revenue and conversion data on calls from your CRM

  • Add or remove custom tags on calls for categorization and reporting


Setting Up Inbound Webhooks

  1. Navigate to Webhooks > Incoming in your MojaAI dashboard

  2. Click Create Webhook

  3. Choose the webhook type (call_data, update_revenue, or update_tags)

  4. Save the webhook — you'll receive an authentication key and webhook URL


Authentication

Each inbound webhook has a unique authentication key. Include the key as a query parameter in your requests:

POST https://webhooks.moja.cloud/{webhook_type}?moja_auth_key={your_auth_key}

The moja_auth_key parameter is required on every request. Requests without a valid key will return a 401 Unauthorized error.


Webhook Types

MojaAI supports three types of inbound webhooks, each with its own endpoint and request structure:

Type

Endpoint

Purpose

call_data

/call-data

Pass caller metadata before or during call routing

update_revenue

/update-revenue

Update revenue and conversion data on calls

update_tags

/update-tags

Add or remove custom tags on calls


Call Data Webhook

Use the call_data webhook to pass caller metadata into MojaAI. This data is matched to incoming calls by caller ID and can be used for routing decisions, custom tags, and reporting.

Request Headers

Content-Type: application/json

Request Body

{
  "caller_id": "+13105559876",
  "lead_source": "google_ads",
  "ad_campaign": "medicare_q1",
  "landing_page": "medicare-info"
}

Fields

Field

Type

Required

Description

caller_id

string

Yes

The caller's phone number (used to match to incoming calls)

transaction_id

string

No

Unique ID for idempotency (prevents duplicate processing)

Any other fields

string

No

Stored as custom data and applied as tags if they match defined custom tags

Any additional fields you send (beyond caller_id and transaction_id) are stored with the request. When a call comes in from the matching caller ID, fields that correspond to custom tags you've defined in MojaAI are automatically applied to the call.

Response

Success (200 OK)

{
  "success": true,
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

How Call Matching Works

When a call arrives, MojaAI checks for call_data webhook requests that match the caller's phone number. If a match is found, the data from the webhook is applied to the call. The lookback window is configurable per webhook (default: 15 days).

Typical flow:

  1. Your system sends caller data to the call_data webhook

  2. A call comes in from that phone number

  3. MojaAI matches the call to the webhook data

  4. Custom tag values from the webhook data are applied to the call

  5. State and ZIP code are updated if included in the data


Update Revenue Webhook

Use the update_revenue webhook to update revenue amounts on completed calls. This is useful when conversions happen after the call ends (e.g., a sale closes days later).

Request Headers

Content-Type: application/json

Request Body

Identify the call by call_log_id:

{
  "call_log_id": "abc123-def456-ghi789",
  "revenue_paid_out": 150.00
}

Or identify the call by phone_number:

{
  "phone_number": "+13105559876",
  "revenue_paid_out": 150.00
}

Fields

Field

Type

Required

Description

call_log_id

string

Yes

The MojaAI call log ID. Accepts call_log_id, callLogId, call_sid, or callSid

phone_number

string

Yes

The caller's phone number. Accepts phone_number or phoneNumber

revenue_paid_out

number

Yes

Revenue amount (USD). Accepts revenue_paid_out or revenuePaidOut

transaction_id

string

No

Unique ID for idempotency (prevents duplicate processing)

*Either call_log_id or phone_number must be provided. If both are provided, call_log_id takes priority.

Behavior

  • If the call's converted_at timestamp is not set, it is automatically set to the current time when revenue is updated

  • When matching by phone_number, the system looks back a configurable number of days (1–7, default: 7) and may match multiple calls

  • Revenue can be updated on both active (live) and completed calls

  • For active calls, the revenue update is applied in real-time via the call session

Response

Success (200 OK)

{
  "success": true,
  "call_log_ids": ["abc123-def456-ghi789"],
  "revenue_paid_out": 150.00,
  "active_call_log_ids": ["abc123-def456-ghi789"]
}

Field

Description

call_log_ids

All call log IDs that were updated

revenue_paid_out

The revenue amount that was applied

active_call_log_ids

Call log IDs for calls that were still active when updated (only included if there are active calls)


Update Tags Webhook

Use the update_tags webhook to add or remove custom tags on calls.

Request Headers

Content-Type: application/json

Request Body

Adding tags:

{
  "call_log_id": "abc123-def456-ghi789",
  "add": {
    "lead_quality": "high",
    "disposition": "sale_completed"
  }
}

Removing tags:

{
  "call_log_id": "abc123-def456-ghi789",
  "remove": ["pending_review", "needs_callback"]
}

Adding and removing in the same request:

{
  "phone_number": "+13105559876",
  "add": {
    "disposition": "sale_completed"
  },
  "remove": ["pending_review"]
}

Fields

Field

Type

Required

Description

call_log_id

string

Yes

The MojaAI call log ID. Accepts call_log_id, callLogId, call_sid, or callSid

phone_number

string

Yes

The caller's phone number. Accepts phone_number or phoneNumber

add

object

Yes

Tags to add as key-value pairs: { "tag_key": "tag_value" }

remove

array

Yes

Tag keys to remove: ["tag_key1", "tag_key2"]

transaction_id

string

No

Unique ID for idempotency (prevents duplicate processing)

*Either call_log_id or phone_number must be provided.

**At least one of add or remove must be provided.

Behavior

  • Tags can be updated on both active (live) and completed calls

  • For active calls, tag updates are applied in real-time via the call session

  • Adding a tag that already exists updates its value

  • Removing a tag that doesn't exist is a no-op (no error)

  • When matching by phone_number, the system looks back a configurable number of days (1–7, default: 7)

Response

Success (200 OK)

{
  "success": true,
  "call_log_ids": ["abc123-def456-ghi789"],
  "added": [{"lead_quality": "high"}, {"disposition": "sale_completed"}],
  "removed": ["pending_review"],
  "active_call_log_ids": ["abc123-def456-ghi789"]
}

Field

Description

call_log_ids

All call log IDs that were updated

added

Tags that were added (as key-value objects)

removed

Tag keys that were removed

active_call_log_ids

Call log IDs for calls that were still active when updated (only included if there are active calls)


Identifying Calls

To update revenue or tags, you need either the call_log_id or the caller's phone_number.

Using call_log_id

The call_log_id uniquely identifies a specific call. You can obtain it from:

1. Outbound webhook payloads — Include the [CALL_ID] tag in your outbound webhook template:

{
  "call_id": "[CALL_ID]",
  "caller": "[CALLER_ID]",
  "campaign": "[CAMPAIGN_NAME]"
}

2. URL parameters — Configure your target to append the call ID to a redirect URL or form submission.3. Dashboard — Find the call log ID in your call logs in the MojaAI dashboard.

Using phone_number

When you provide phone_number instead of call_log_id, MojaAI looks up recent calls from that phone number within the configured lookback window. This can match multiple calls if the same caller has made more than one call within the window.

Lookback window: Configurable per webhook (1–7 days, default: 7 days).


Idempotency

All three webhook types support idempotent requests using the transaction_id field. When you include a transaction_id:

  • If a request with the same transaction_id has already been processed, the original response is returned

  • If a request with the same transaction_id is currently being processed, a 409 Conflict is returned

  • The transaction_id is scoped to your organization

This prevents duplicate processing when retrying failed requests.

{
  "call_log_id": "abc123-def456-ghi789",
  "revenue_paid_out": 150.00,
  "transaction_id": "txn_20260206_001"
}


Error Codes

Code

Error

Description

400

Missing required parameter

A required field is missing (e.g., caller_id for call data, revenue_paid_out for update revenue)

401

Unauthorized

Invalid or missing moja_auth_key

403

Forbidden

Call log does not belong to your organization

404

Not found

Call log not found (verify call_log_id or phone_number and check the lookback window)

409

Conflict

Duplicate transaction_id — request is already being processed

429

Rate limited

Too many requests (see Rate Limits below)

500

Server error

Internal server error


Rate Limits

Limit

Value

Default

100 requests per minute

Rate limits are configurable per webhook and can be set to per-minute, per-hour, or per-day periods. Contact your account manager if you need a higher limit.


Best Practices

  1. Use call_log_id when possible — It's more precise than phone_number matching, which can affect multiple calls

  2. Include transaction_id — Prevents duplicate processing when retrying requests

  3. Handle errors — Implement retry logic with exponential backoff for 429 and 500 errors

  4. Send data promptly — For call_data webhooks, send caller metadata before the call arrives for best results

  5. Define custom tags first — Create your custom tags in the MojaAI dashboard before sending call_data webhooks so the values are automatically applied to calls


Integration Examples

cURL — Update Revenue

curl -X POST "https://webhooks.moja.cloud/update-revenue?moja_auth_key=your_auth_key" \
  -H "Content-Type: application/json" \
  -d '{
    "call_log_id": "abc123-def456-ghi789",
    "revenue_paid_out": 150.00,
    "transaction_id": "txn_20260206_001"
  }'

cURL — Send Call Data

curl -X POST "https://webhooks.moja.cloud/call-data?moja_auth_key=your_auth_key" \
  -H "Content-Type: application/json" \
  -d '{
    "caller_id": "+13105559876",
    "lead_source": "google_ads",
    "campaign_name": "medicare_q1"
  }'

cURL — Update Tags

curl -X POST "https://webhooks.moja.cloud/update-tags?moja_auth_key=your_auth_key" \
  -H "Content-Type: application/json" \
  -d '{
    "call_log_id": "abc123-def456-ghi789",
    "add": {"disposition": "sale_completed"},
    "remove": ["pending_review"]
  }'

Python — Update Revenue

import requestsresponse = requests.post(
    "https://webhooks.moja.cloud/update-revenue",
    params={"moja_auth_key": "your_auth_key"},
    json={
        "call_log_id": "abc123-def456-ghi789",
        "revenue_paid_out": 150.00,
        "transaction_id": "txn_20260206_001"
    }
)print(response.json())

JavaScript — Update Tags

const response = await fetch(
  'https://webhooks.moja.cloud/update-tags?moja_auth_key=your_auth_key',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      call_log_id: 'abc123-def456-ghi789',
      add: { disposition: 'sale_completed', lead_quality: 'high' },
      remove: ['pending_review']
    })
  }
);const result = await response.json();
console.log(result);


Troubleshooting

Problem: Getting "Missing caller_id parameter" on call data webhook

  • Solution: Ensure you include a caller_id field in your request body or query parameters. The field name must be caller_id or from.

Problem: Getting "Call log not found" on update revenue or tags

  • Solution: Verify the call_log_id is correct, or if using phone_number, check that the call falls within the lookback window (default: 7 days). Call log IDs are case-sensitive.

Problem: Getting "Unauthorized" error

  • Solution: Check that your moja_auth_key is included as a query parameter (not in the URL path or headers). Verify the key is correct and the webhook has not been deleted.

Problem: Revenue update not reflected in reports

  • Solution: Updates may take a moment to process. If using phone_number matching, verify the phone number format matches what's in MojaAI. Check the response for call_log_ids to confirm which calls were updated.

Problem: Tags not appearing on calls

  • Solution: For call_data webhooks, ensure the tag keys you're sending match custom tags defined in your MojaAI dashboard. For update_tags, tags are applied directly — check the response added array to confirm.


Need Help?


Did this answer your question?