LeadBind Docs

Tools reference

Every tool your assistant can call, and exactly what each returns.

Your assistant picks which tool to call, so you never name one directly. This page is here for when you want to know exactly what it can reach, what to pass, and what comes back.

Each tool needs one of three permissions: read, write, or dial. See Keys and permissions. A key only sees the tools its scopes allow, so a read-only key never even lists the write tools.

The input tables below are generated from the server's own tool definitions on every build, so they cannot drift from what the endpoint actually accepts. The return shapes further down are written by hand against each handler.

How a tool call is shaped

Every tool runs over the MCP endpoint as a JSON-RPC 2.0 tools/call. Your assistant builds this for you; the CLI wraps it; and you can send it by hand with curl. A call names a tool and passes arguments:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": { "name": "list_leads", "arguments": { "stage": "new", "limit": 5 } }
}

The result comes back with the tool's own JSON as a string inside content[0].text:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      { "type": "text", "text": "{\n  \"leads\": [ ... ]\n }" }
    ]
  }
}

Safety rails on every write

Every write tool and every dial tool accepts two optional fields, because the caller is an AI and an AI retries on a timeout:

  • idempotency_key is any unique string you generate for this write. Retrying with the same key returns the original result instead of writing a second time, with replayed: true added so you can tell. Strongly recommended on every write, and it is the one thing standing between a flaky network moment and a lead getting called twice or three drip sequences getting built.
  • dry_run, when true, validates and describes what the tool would write, and changes nothing. It comes back as { "dry_run": true, "would_create": ... } or the equivalent would_set / would_add / would_record / would_verify. This is what lets an assistant plan a whole account build, show you exactly what it will create, and only then run it for real.

Neither is repeated in the input tables below. Assume both are available on every write and dial tool.

Working across an organization

Most keys act on exactly one account. An organization key, which is any key created by an account that owns or manages an organization, can also act on the other seats in that same organization.

  • Call list_accounts first. An organization key gets back the org_id and every seat, each with an account_id. A single-account key gets back just its own.
  • Pass that account_id on any tool to run it against that seat. It is advertised on the go-to-market tools, where working across seats is the point, and the server honors it on every tool.
  • A single-account key that names another account is refused with -32003 before the tool runs. A team lead can only ever reach seats inside their own organization.

See Keys and permissions for the full rule.

28 tools, grouped by the permission each one needs.

Reading

14 tools, permission read. A read-only key can call every tool in this section and nothing else.

list_leads

List leads

List the account's leads, newest first. Optionally filter by pipeline stage. Each lead comes back with its address and map coordinates when it has them, so a lead you created with an address reads back the same way.

Input Type Required What it is
stage string no Return only leads sitting in this pipeline stage. Omit to return every stage. One of: new, contacted, callback, hot, booked, sold, lost.
limit number no Maximum rows to return. Defaults to 25, capped at 100.

Behavior: changes nothing.

list_calls

List recent calls

List recent calls for the account with outcome, direction and duration. Use for 'what happened on the phone today'.

Input Type Required What it is
limit number no Maximum rows to return. Defaults to 25, capped at 100.
direction string no Return only calls in this direction. Omit to return both. One of: inbound, outbound.

Behavior: changes nothing.

list_appointments

List upcoming appointments

List upcoming appointments for the account. Use for 'what is on my calendar'.

Input Type Required What it is
limit number no Maximum appointments to return. Defaults to 25, capped at 100.

Behavior: changes nothing.

get_call_metrics

Call performance metrics

Call performance over a period: total, connected, voicemail, and how many reached a real person. Reads the one canonical call vocabulary, so these numbers match the dashboard exactly.

Input Type Required What it is
days number no How many days back to measure. Defaults to 30, capped at 730.

Behavior: changes nothing.

get_next_actions

What to work on now

The agent's actual to-do list right now: leads that went cold, connected calls that never got a follow-up, and appointments coming up. Call this when asked 'what should I do today', 'what needs attention', or at the start of a work session. Returns work to be done, not a data dump. Each item includes the lead id and phone so you can act on it with other tools.

No inputs.

Behavior: changes nothing.

get_availability

Open booking slots

Open appointment slots for the account's booking calendar over the next two weeks. Call this BEFORE book_appointment so you offer a real time instead of guessing one.

Input Type Required What it is
timezone string no IANA timezone the returned slots are expressed in, for example America/Chicago. Defaults to America/Chicago.

Behavior: changes nothing.

list_lead_lists

List saved lead lists

List the account's saved lead lists with each list's member count and a per-stage rollup (new, contacted, booked, sold, and so on). Use this to find a listId to pass to run_list, and to watch results roll up as calls complete.

No inputs.

Behavior: changes nothing.

list_calendars

List booking calendars

List the account's named booking calendars and their settings.

No inputs.

Behavior: changes nothing.

list_drips

List drip sequences

List the account's drip sequences and their steps.

No inputs.

Behavior: changes nothing.

get_account_config

Read account configuration

Read the account's pipeline stages, custom lead field definitions, and automation settings. Use before writing config so you patch rather than clobber.

No inputs.

Behavior: changes nothing.

list_accounts

List reachable accounts

List the accounts this key can act on. A per-account key returns just its own account. An organization key (held by a team lead) returns every seat in the org, each with an account_id to pass as account_id on any GTM tool to act on that seat.

No inputs.

Behavior: changes nothing.

score_lead

Score a lead

Score a saved lead now and return the reasons. Gives the 1-99 priority score, the hot/warm/cold tier, the fit and intent dimensions, the A-D x 1-4 grid, the routing call, and the factor breakdown. This is a read: it computes and explains, and writes nothing. Fit is null when the account has no closed-deal history to judge source fit from, which is honest, not an error.

Input Type Required What it is
leadId string yes Id of a saved lead (from list_leads).
account_id string no Organization keys only: the seat to act on, from list_accounts. Omit to use the key's own account. A per-account key may only ever use its own account.

Behavior: changes nothing.

get_closing_brief

Closing call brief

Build the closing-call brief for a saved lead: who they are, what they need, their pain points, the deal state, a price recommendation with its inputs shown, a talk track, and the next step. Every line cites the record it came from; a lead with no activity yet returns empty sections on purpose rather than guesses. Returns the structured brief and a ready-to-read text version.

Input Type Required What it is
leadId string yes Id of a saved lead (from list_leads).
account_id string no Organization keys only: the seat to act on, from list_accounts. Omit to use the key's own account. A per-account key may only ever use its own account.

Behavior: changes nothing.

get_market_intel

Market intel

Real go-to-market intel distilled from this account's vertical: per-source win rates, price anchors by tier, winning hooks, and losing patterns, all counted from closed deals (never guessed or competitor data). Pass an asset_type to also get the current winning assets of that kind. Returns available:false when not enough deals have closed yet.

Input Type Required What it is
asset_type string no Optional: also return the current best assets of this kind. One of: sms_step, email_step, sequence, form, funnel_headline, ad_copy, pre_nurture, closing_pitch.
channel string no Optional: narrow the winning assets to one channel. One of: sms, email, linkedin, voice, web.
account_id string no Organization keys only: the seat to act on, from list_accounts. Omit to use the key's own account. A per-account key may only ever use its own account.

Behavior: changes nothing.

Writing

12 tools, permission write. These need a key with write. Every one of them also accepts idempotency_key and dry_run (see the safety rails above), which are not repeated in the tables.

book_appointment

Book an appointment

Book an appointment on the account's calendar. Requires a slot returned by get_availability. The customer must have agreed to be contacted; pass consent only when they actually have.

Input Type Required What it is
startTime string yes ISO 8601 start time, taken from a slot get_availability returned.
name string yes Full name of the person the appointment is for.
email string yes Email address the confirmation is sent to.
phone string yes Contact phone number for the person being booked, US format.
consent boolean yes True only if the customer actually agreed to be contacted.
timezone string no IANA timezone the start time is expressed in, for example America/Chicago. Defaults to America/Chicago.

create_lead

Create a lead

Create a new lead on the account. Pass an address when you have one and the lead appears on the door-mode map, so a business your assistant found on a map becomes a stop a rep can walk to.

Input Type Required What it is
name string yes Full name of the person, or the business name.
phone string yes US phone number. Anything that is not a digit is ignored, and the last ten digits are stored.
email string no Email address for the lead, if you have one.
notes string no Free-text context to store on the lead, such as what they asked for.
address string no Street address, for example 123 Main St. Give this and the lead can appear on the door-mode map.
city string no City the address is in.
state string no Two-letter US state code, for example TX.
zip string no US postal code.

update_lead

Update a lead

Update a saved lead: its contact details, its pipeline stage, its notes, or its address. Only the fields you send are changed; everything else is left alone. Get the leadId from list_leads.

Input Type Required What it is
leadId string yes The lead to update, from list_leads.
name string no Full name of the person, or the business name.
phone string no US phone number. Anything that is not a digit is ignored, and the last ten digits are stored.
email string no Email address for the lead.
notes string no Replaces the notes on the lead. Read the lead first if you mean to append rather than replace.
stage string no Move the lead to this pipeline stage. One of: new, contacted, callback, hot, booked, sold, lost.
address string no Street address, for example 123 Main St. Give this and the lead can appear on the door-mode map.
city string no City the address is in.
state string no Two-letter US state code, for example TX.
zip string no US postal code.

find_businesses

Find businesses

Search Google Maps for businesses in a place and save them to the account as leads, with their street address so they appear on the door-mode map. This one costs credits, so it works in two steps: call it first to get the price and the balance, then call it again with confirm set to true to actually run it. Available on Right Hand and Front Desk Pro. Set enrich to also read each business's website for what they do and a contact email, priced per site on top.

Input Type Required What it is
query string no The full search, for example: roofing companies in Katy TX. Give this, or give niche and city.
niche string no Kind of business to look for, for example roofing contractor.
city string no Where to look, for example Katy TX.
limit number no How many businesses to look for. Defaults to 20, capped at 50. The price is per result.
enrich boolean no When true, each result that has a website gets one page read, which adds a note about what they do and any contact email found. Priced per site read, on top of the search.
confirm boolean no Must be true to actually run the search and charge for it. Without it you get the price, the balance and nothing else.

create_calendar

Create a booking calendar

Create a named booking calendar. Slugs are unique per account, so re-running with an existing slug is refused rather than silently duplicating.

Input Type Required What it is
slug string yes URL-safe identifier, unique within this account. Anything outside lowercase letters, digits and hyphens is replaced with a hyphen.
name string yes Display name customers see on the booking page.
description string no Short blurb shown under the calendar name on the booking page.
timezone string no IANA timezone this calendar's hours are expressed in, for example America/Chicago.
slot_minutes number no Length of one bookable slot, in minutes.
buffer_minutes number no Gap held open after each appointment, in minutes.
min_notice_minutes number no How far ahead a customer must book, in minutes. Blocks last-minute bookings.
booking_window_days number no How many days into the future this calendar accepts bookings.
auto_confirm boolean no True to confirm bookings automatically instead of leaving them pending review.

set_availability

Set weekly availability

Set the account's default weekly availability and booking rules. weekly maps each weekday to its open windows.

Input Type Required What it is
timezone string no IANA timezone the weekly hours are expressed in, for example America/Chicago.
slot_minutes number no Length of one bookable slot, in minutes.
buffer_minutes number no Gap held open after each appointment, in minutes.
min_notice_minutes number no How far ahead a customer must book, in minutes.
weekly object no Opening hours per weekday, in the account timezone. Each of the seven day keys maps to a list of open windows. Fields: sun, mon, tue, wed, thu, fri, sat.

create_drip

Create a drip sequence

Create a drip sequence with its ordered steps. Steps send on a delay after enrollment. Creating a sequence does NOT enroll anyone.

Input Type Required What it is
name string yes Internal name for the sequence, shown in the account's drip list.
active boolean no True to start sending as soon as leads are enrolled. Defaults to false.
auto_enroll_new boolean no Enroll newly created leads automatically.
auto_enroll_cold boolean no Enroll existing leads automatically once they go cold (new or contacted stage, no contact in 4 or more days).
steps array of object yes The steps to send, in the order they should go out. Each entry has: delay_hours (required), channel (required), subject, body (required).

set_pipeline_config

Replace pipeline stages

Replace the account's pipeline stage configuration. Read get_account_config first, because this overwrites the whole object.

Input Type Required What it is
pipeline_config object yes The complete pipeline configuration. This replaces the stored object, so read get_account_config first and send the whole thing back. Fields: stages (required).

create_lead_field

Add a custom lead field

Add a custom lead field definition. Appends to the existing definitions rather than replacing them.

Input Type Required What it is
key string yes Machine key, unique within the account. Anything outside lowercase letters, digits and underscores is replaced with an underscore.
label string yes Display name shown on the lead record.
type string no How the value is entered and stored. Defaults to text. One of: text, number, date, select, boolean.
options array of string no The choices offered, for a select field only.

request_payment

Request a card payment

Create a payment request the customer can pay by card, and return a pay-link URL to send them. Money goes to the account's own connected Stripe. Pass amountCents (e.g. 25000 for $250.00) and a short description; optionally a leadId to attach it to a saved lead. Requires the account's Stripe to be connected. If it is not, this returns needsConnect.

Input Type Required What it is
amountCents number yes Amount to charge, in cents. 25000 = $250.00. Minimum 100.
description string yes What the payment is for (shown to the customer on the pay page)
leadId string no Optional saved lead to attach this payment to

verify_lead

Verify a lead

Re-verify a saved lead's email deliverability and phone line-type (mobile, landline, or VoIP), optionally enrich it, and store the result on the lead. Returns the verification detail and skip_dial (true when the number is proven invalid or VoIP, so it should not be dialed). An unchecked leg reports "unknown", never a guess.

Input Type Required What it is
leadId string yes Id of a saved lead (from list_leads).
force boolean no Bypass the cache and re-check from scratch.
enrich boolean no Also run the public-web enrichment leg.
account_id string no Organization keys only: the seat to act on, from list_accounts. Omit to use the key's own account. A per-account key may only ever use its own account.

record_close_outcome

Record a won or lost deal

Record a deal as won or lost so the GTM learning loop can learn from a real close. A won REQUIRES deal_id (a closed deal this account owns) and amount_cents. Optionally attach the lead, the reason it was won or lost, the price offered, and the asset/play ids that were in play, so the win is attributed back to what produced it. Nothing is counted from a timer; only this closer-confirmed outcome moves the loop.

Input Type Required What it is
result string yes Whether the deal closed or was lost. One of: won, lost.
deal_id string no Required on a won: the closed deal (agent_deals) this account owns.
lead_id string no Optional saved lead the close came from (from list_leads).
amount_cents number no Required on a won: what actually closed, in whole cents (25000 = $250.00).
price_offered_cents number no Optional: the price offered, in whole cents.
reason_code string no Why it was won or lost, as one of the standard codes. One of: price, timing, competitor, not_qualified, no_show, ghosted, other.
context string no Optional free-text note on why it was won or lost (the closer's ground truth).
variant_ids array of string no gtm_asset_variant ids that touched this lead.
play_ids array of string no call_insights play ids that were in play.
score_at_close number no Optional: the lead's score when it closed (calibrates scoring).
account_id string no Organization keys only: the seat to act on, from list_accounts. Omit to use the key's own account. A per-account key may only ever use its own account.

Calling

Two tools, permission dial. These need a key with dial, which is never implied by write. They place real phone calls to real people.

place_call

Place an AI phone call

Place an outbound AI phone call from the account's own number. The AI agent holds the conversation, books the appointment, and the call lands in list_calls when it completes. Dial a saved lead by leadId (uses the consent already on file), or an ad-hoc number with phone and name. Calls are DNC-scrubbed and consent-gated; a blocked number returns the reason instead of dialing.

Input Type Required What it is
leadId string no Id of a saved lead to call (from list_leads). Preferred: uses the lead's consent on file.
phone string no Ad-hoc US number to call when no leadId is given.
name string no Name of the person being called, on an ad-hoc dial.

Behavior: places a real phone call, so it reaches outside LeadBind.

run_list

Run AI calls against a list

Run outbound AI calls against a set of leads at once. Pass a listId (from list_lead_lists) to call every member of a saved list, or leadIds (from list_leads) to call a hand-picked set. Each call goes out from the account's own number, DNC-scrubbed, consent-gated, and only inside legal calling hours; leads that cannot be called are returned with the reason instead of being forced. Optionally cap this run with maxCalls. Returns a per-lead summary of what was placed and what was skipped. Outcomes (connected, qualified, booked) land as each call finishes; read them with list_calls, get_call_metrics, or list_leads.

Input Type Required What it is
listId string no Saved list to run (from list_lead_lists). Calls every member.
leadIds array of string no Hand-picked lead ids to run (from list_leads). Use instead of listId, not with it.
maxCalls number no Optional cap on how many calls this run places. Defaults to the account's remaining daily-cap room.

Behavior: places a real phone call, so it reaches outside LeadBind.

What each tool returns

Return shapes are not part of the tool schema, so these are read from each handler rather than generated. Every one of them arrives as JSON text inside result.content[0].text.

Reading

list_leads

{ "leads": [
  { "id": "ld_...", "name": "Maria Lopez", "phone": "+1...", "email": null, "stage": "contacted", "source": "web-form", "created_at": "..." }
] }

list_calls. caller is always the other party, whichever end that is, so you never have to reason about which of from_number / to_number was you. See Calls and outcomes for what each outcome means.

{ "calls": [
  { "created_at": "...", "direction": "inbound", "outcome": "booked", "duration_seconds": 142,
    "from_number": "+1...", "to_number": "+1...", "caller": "+1..." }
] }

Note: This returns the outcome of a call, never the transcript or the recording. Those are not available to any assistant, at any scope. See What we send.

list_appointments

{ "appointments": [
  { "id": "ap_...", "contact_name": "Dan Reyes", "contact_phone": "+1...", "starts_at": "...",
    "status": "confirmed", "source": "ai-call", "meeting_url": null }
] }

get_call_metrics returns the window you asked for plus the dashboard's own call breakdown, unmodified. It is the same database function the dashboard reads, so these numbers match the app exactly rather than being a second, drifting definition of "answered".

{
  "days": 30,
  "breakdown": {
    "inbound":  { "total": 120, "connected": 96, "voicemail": 18, "answered": 71 },
    "outbound": { "total": 90,  "connected": 42, "voicemail": 23, "answered": 26 },
    "outcomes": [ { "outcome": "booked", "count": 31 } ],
    "intents":  [ { "intent": "quote", "count": 44 } ],
    "hangups":  [ { "reason": "user_hangup", "count": 52 } ],
    "qa": { "rated": 40, "flagged": 3, "good": 31, "success": 28 },
    "latency": { "p50": 780, "p90": 1420 }
  }
}

The breakdown also carries a count of stored recordings inside the app. It is stripped on the way out here, along with anything else whose field name mentions a recording or a transcript, so it never reaches an assistant. breakdown is null when the account has no calls in the window.

get_next_actions returns work, not records. It is the one to start with.

{
  "summary": "3 lead(s) contacted but untouched for 3+ days, 2 real conversation(s) in the last week with no booking, 1 appointment(s) in the next 48 hours.",
  "stale_leads": [
    { "id": "ld_...", "name": "Maria Lopez", "phone": "+1...", "stage": "contacted", "updated_at": "...", "created_at": "..." }
  ],
  "conversations_without_booking": [
    { "created_at": "...", "from_number": "+1...", "outcome": "answered", "duration_seconds": 96 }
  ],
  "upcoming_appointments": [
    { "id": "ap_...", "contact_name": "Dan Reyes", "contact_phone": "+1...", "starts_at": "...", "status": "confirmed", "meeting_url": null }
  ]
}

Ask it: "What should I work on today?"

get_availability returns days, not a flat list of times, plus the horizon the business actually set. It already accounts for your hours, your buffers, your minimum notice, your daily cap, your blackout dates, and anything on your connected Google Calendar.

{
  "days": [
    { "date": "2026-08-31", "slots": ["2026-08-31T14:00:00-05:00", "2026-08-31T14:30:00-05:00"] }
  ],
  "agent": { "name": "Maria Lopez", "businessName": "Lopez Roofing" },
  "bookingWindowDays": 14,
  "calendar": { "slug": "roof-inspections", "name": "Roof Inspections", "description": null,
                "slotMinutes": 30, "autoConfirm": false, "questions": [] }
}

calendar is null for an account booking on its default weekly availability rather than a named calendar. An account with no booking slug set up yet gets { "error": "..." } instead.

Ask it: "When am I free Thursday?"

list_calendars

{ "calendars": [
  { "id": "cal_...", "slug": "roof-inspections", "name": "Roof Inspections", "description": null,
    "is_default": true, "auto_confirm": false, "timezone": "America/Chicago", "slot_minutes": 30,
    "buffer_minutes": 15, "min_notice_minutes": 60, "booking_window_days": 14, "active": true }
] }

list_lead_lists gives you the listId to hand to run_list, and the per-stage rollup to watch results land.

{ "lists": [
  { "id": "ll_...", "name": "March storm leads", "dialing_enabled": true, "created_at": "...",
    "stats": { "total": 214, "new": 90, "contacted": 96, "booked": 22, "sold": 6 } }
] }

list_drips

{ "sequences": [
  { "id": "seq_...", "name": "No-answer 3-touch", "active": true, "auto_enroll_new": false, "auto_enroll_cold": true,
    "steps": [
      { "sequence_id": "seq_...", "step_order": 1, "delay_hours": 1, "channel": "sms", "subject": null,
        "body": "Hi {{name}}, sorry we missed you..." }
    ] }
] }

get_account_config returns the row itself, with no wrapper.

{ "vertical": "roofing", "workspace_mode": "sales", "timezone": "America/Chicago",
  "pipeline_config": { "...": "..." }, "lead_field_defs": [], "automation_settings": { "...": "..." } }

list_accounts. An organization key gets org_id too; a single-account key gets one row and no org_id.

{ "org_id": "org_...", "accounts": [
  { "account_id": "ag_...", "name": "Lopez Roofing", "role": "owner" },
  { "account_id": "ag_...", "name": "North crew", "role": "member" }
] }

score_lead computes and explains, and writes nothing. fit is null when the account has no closed-deal history to judge source fit from, which is honest rather than an error.

{ "ok": true, "leadId": "ld_...", "score": 78, "tier": "hot", "fit": "B", "intent": 2,
  "grid": "B2", "routing": "call_now", "reason": "...", "factors": [ { "...": "..." } ] }

get_closing_brief returns the structured brief and a ready-to-read text version of the same thing. A lead with no activity yet returns empty sections on purpose rather than guesses.

{ "ok": true, "brief": { "...": "..." }, "text": "Closing brief for Maria Lopez\n..." }

get_market_intel fills in once enough deals have closed and says so plainly until then.

{ "ok": true, "available": true, "based_on_deals": 61, "confidence": 0.72,
  "source_win_rates": { "web-form": 0.31 }, "price_anchors_cents": { "hot": 240000 },
  "winning_hooks": ["..."], "losing_patterns": ["..."], "experiment": "...",
  "winning_assets": [], "note": "Real intel distilled from this vertical's closed deals..." }

With nothing distilled yet it returns { "ok": true, "available": false, "note": "...", "winning_assets": ... } and never invents a competitor price or a rate.

Writing

create_lead. The phone is normalized to a 10-digit US number, so digits with spaces, dashes, or parentheses all land the same.

{ "ok": true, "leadId": "ld_..." }

Ask it: "Add Maria Lopez, her number, roof leak, called this morning."

book_appointment books onto your real calendar and triggers the normal confirmation.

{ "ok": true, "when": "Thursday, August 31 at 2:00 PM CDT", "status": "confirmed",
  "manageUrl": "https://leadbind.org/b/..." }

when is the human-readable time in the viewer's timezone, not the ISO string you sent. On a calendar that takes a deposit, the response also carries checkout_url, a Stripe Checkout link the customer must complete, and status is pending_payment until they do.

Two things are enforced and neither is negotiable:

  1. startTime must come from get_availability. A guessed time is rejected rather than double-booking you.
  2. consent must be true, and it must be real. It means the person actually agreed to this appointment and to being contacted about it. It is not a checkbox to satisfy. See Consent and opt-outs.

Ask it: "Book Maria for Thursday at 2."

create_calendar

{ "ok": true, "calendarId": "cal_...", "slug": "roof-inspections" }

set_availability tells you which fields it actually changed.

{ "ok": true, "set": ["timezone", "slot_minutes", "weekly"] }

create_drip. Creating a sequence does not enroll anyone by itself.

{ "ok": true, "sequenceId": "seq_...", "steps": 3 }

Ask it: "Set up a three-touch follow-up for leads who do not answer."

set_pipeline_config replaces the whole object, so read get_account_config first and pass the merged result. Do this one with dry_run: true the first time.

{ "ok": true }

create_lead_field appends to your existing definitions rather than replacing them, and refuses a key that already exists.

{ "ok": true, "field": { "key": "roof_type", "label": "Roof type", "type": "select",
  "options": ["Shingle", "Metal", "Tile"] }, "total": 4 }

verify_lead stores the result on the lead, which is why it is a write. An unchecked leg reports "unknown", never a guess.

{ "ok": true, "leadId": "ld_...", "verified_at": "...",
  "verification": { "email": { "...": "..." }, "phone": { "line_type": "mobile" } },
  "skip_dial": false }

request_payment creates a payment request and hands back a pay-link URL you send the customer. They pay by card, the money lands in your own connected Stripe account, and LeadBind takes its platform fee. It never sees a card number.

{ "ok": true, "url": "https://leadbind.org/estimate/dl_...", "dealId": "dl_...",
  "amountCents": 25000, "applicationFeeCents": 750 }

Until your Stripe is connected (Settings, then Payments) it returns { "error": "Connect your Stripe account first...", "needsConnect": true } instead of a half-made request.

Ask it: "Send Maria a $250 deposit link for the roof job."

record_close_outcome is the only place the learning loop takes a real won or lost. Nothing is counted from a timer.

{ "ok": true, "outcome_id": "go_...", "vertical": "roofing", "attributed_variants": 2 }

Calling

place_call places one real outbound call.

{ "ok": true, "called": true, "to": "+1...", "callId": "call_..." }

callId is the provider's own id for the call, and is null when the provider accepted the call without returning one. The dial permission is separate from write and is off by default. Reading your leads and dialing a real person are not the same risk, so place_call never rides in on write access. Every call it places runs through the exact same core as a call you place yourself in the app, so every guard rides along: rate limit, billing gate, your plan's calling entitlement, consent-only mode, per-lead consent, and a Do-Not-Call scrub. A blocked number returns the reason instead of dialing.

Ask it: "Call the lead I just added and book them for Tuesday."

run_list dials a whole list or a hand-picked set, and reports per lead what actually happened. It never reports a made-up outcome: calls are placed here, and connected, qualified and booked land later, read with list_calls, get_call_metrics, or list_leads.

{
  "ok": true,
  "target": { "type": "list", "listId": "ll_...", "requested": 40, "considered": 40 },
  "placed": 12, "skipped": 28, "failed": 0,
  "capRoomBefore": 12, "reachedCap": true,
  "results": [
    { "leadId": "ld_...", "name": "Maria Lopez", "phone": "+1...", "status": "placed", "to": "+1..." },
    { "leadId": "ld_...", "name": "Dan Reyes", "phone": "+1...", "status": "skipped", "reason": "outside_calling_hours" },
    { "leadId": "ld_...", "name": null, "phone": null, "status": "skipped", "reason": "do_not_call" }
  ],
  "note": "Calls are placed, not yet completed..."
}

Skip reasons are real guard results, never invented: do_not_call, outside_calling_hours, daily_cap_reached, rate_limited_retry_shortly, lead_not_found. Batch calling applies the lead's own local calling window on top of every guard place_call uses, because a batch runner is autonomous where a single manual dial is a person's judgment. Everything in Consent and opt-outs and Disclosing the AI applies to every call, whoever placed it.

When a tool fails

A tool that cannot do what you asked returns { "error": "..." } inside a normal result, often with a detail field. That is different from a protocol error such as a missing key or a missing scope, which comes back as a JSON-RPC error with a real HTTP status. See Errors.

What is deliberately missing

There is no tool that returns a call transcript, a recording, or an audio URL, and there will not be one. Recorded conversations carry consent rules that vary by state, and the person on that call never agreed to a third-party AI vendor holding their words. LeadBind blocks these fields on the way out, not just by leaving them out of the tool list. See What we send and Call recording.

No tool exposes a stored payment detail, your own LeadBind subscription billing, or another account's data. request_payment creates a pay-link and never sees a card number, and every tool is scoped to the account that owns the key, or for an organization key to a seat inside that same organization.

Was this page helpful?