v1.0Protocol: 2025-03-26

MCP API Reference

Complete developer reference for the DispatchNode MCP server. Covers authentication, the JSON-RPC protocol, all available tools with full I/O schemas, error codes, and SDK examples.

Overview

The DispatchNode MCP server implements the Model Context Protocol (MCP) via the Streamable HTTP transport. It exposes a single endpoint that accepts JSON-RPC 2.0 requests and returns JSON-RPC 2.0 responses.

POSThttps://www.dispatchnode.com/api/mcp

The server supports two access tiers — customer and operator — so AI agents can book jobs without needing an API key, while business owners get full administrative access.

TierAuthToolsWho
CustomerX-Org-Slug header (no key)9 tools incl. book/cancel/reschedule/status + spawn_job_agentAI agents acting on behalf of a customer
OperatorAuthorization: Bearer dnk_...All 47 toolsBusiness owner's CRM / automation

Authentication

Customer Tier: No API key needed. AI agents visiting a site with the DispatchNode widget can call customer tools by passing the org slug. This works the same way the voice widget does — no credentials required.

Customer Tier (No API Key)

For AI agents acting on behalf of customers (e.g., a wedding planner's Claude assistant booking portapotties). Pass the org slug from the <link> tag's data-org-slug attribute.

Customer Requesthttp
POST /api/mcp HTTP/1.1
Host: www.dispatchnode.com
Content-Type: application/json
X-Org-Slug: eventrestroomrentals

Available tools: book_job, check_availability, get_pricing, calculate_dispatch_tco, cancel_job, reschedule_job, get_job_status, get_business_info, spawn_job_agent. Rate limited to 30 req/min and 10 bookings/hour per IP.

Operator Tier (API Key)

For the business owner's own CRM or automation integrations. Full access to all 47 tools.

Key format
dnk_ + 32 random bytes (base64url)
Storage
SHA-256 hash — raw key shown only at creation
Scope
One key = one organization. No cross-tenant access.
Revocation
Instant — revoked keys fail on next request
Prefix
First 12 chars visible for identification (e.g. dnk_a1b2c3d4)
Usage tracking
lastUsedAt updated on each successful validation
Operator Requesthttp
POST /api/mcp HTTP/1.1
Host: www.dispatchnode.com
Content-Type: application/json
Authorization: Bearer dnk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0

JSON-RPC Protocol

All communication uses JSON-RPC 2.0 over HTTP POST. Every request must include:

FieldTypeDescription
jsonrpc"2.0"Must be exactly "2.0"
idstring | numberRequest identifier — echoed in the response
methodstringOne of: initialize, tools/list, tools/call
paramsobjectMethod parameters (optional for initialize and tools/list)

Available methods:

initializeEstablish a session. Returns server info, capabilities, and protocol version.
notifications/initializedClient acknowledgment after initialize. No meaningful response.
tools/listReturns all available tools with their JSON Schema input definitions.
tools/callExecute a tool. Requires params.name and params.arguments.

Session Lifecycle

A typical MCP session follows this sequence:

1
Initialize
{ "jsonrpc": "2.0", "id": 1, "method": "initialize" }
2
Server returns capabilities
{ "protocolVersion": "2025-03-26", "serverInfo": { "name": "dispatchnode", "version": "1.0.0" }, "capabilities": { "tools": {} } }
3
List tools (optional)
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }
4
Call tools (repeat)
{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "book_job", "arguments": { ... } } }
Note:Unlike WebSocket-based MCP transports, Streamable HTTP is stateless. Each POST request is independent — you don't need to maintain a persistent connection. The initialize step is optional but recommended.

Tools Reference

47 tools

All 47 registered tools are documented below (9 customer-tier via X-Org-Slug, 38 operator-only via Bearer dnk_…). Each tool returns a JSON-RPC result with a content array containing a text item with the JSON-stringified response.

book_job

TOOL

Book a new service job for a customer. Creates a job record with scheduling, service type, and contact information.

Input Parameters

ParameterTypeRequiredDescription
customerNamestringrequiredCustomer's full name
customerPhonestringrequiredCustomer phone in E.164 format (+1XXXXXXXXXX)
customerEmailstringoptionalCustomer email address (optional)
serviceAddressstringrequiredService location address
scheduledStartstringrequiredISO 8601 datetime for job start
scheduledEndstringoptionalISO 8601 datetime for job end (optional)
serviceTypestringoptionalService type slug (e.g. 'grease-trap-450-gal')
notesstringoptionalAdditional notes for the dispatcher
priorityenum: normal | urgent | emergencyoptionalJob priority level

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "book_job",
    "arguments": {
      "customerName": "<customerName>",
      "customerPhone": "<customerPhone>",
      "serviceAddress": "<serviceAddress>",
      "scheduledStart": "<scheduledStart>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

check_availability

TOOL

Check available time slots for a given date range. Returns open slots based on calendar, existing bookings, and transit buffers. Supports pagination.

Input Parameters

ParameterTypeRequiredDescription
startDatestringrequiredStart date (ISO 8601)
endDatestringrequiredEnd date (ISO 8601)
serviceTypestringoptionalService type slug to check duration requirements
pagenumberoptionalPage number (1-based, default 1)
pageSizenumberoptionalResults per page (default 20, max 50)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "check_availability",
    "arguments": {
      "startDate": "<startDate>",
      "endDate": "<endDate>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_jobs

TOOL

List jobs with optional status filter. Returns recent jobs with customer info, scheduling, and status. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
statusenum: LEAD | QUOTED | SCHEDULED | IN_PROGRESS | COMPLETED | CANCELLEDoptionalFilter by job status
limitnumberoptionalMax results (default 20, max 100)
offsetnumberoptionalPagination offset

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "list_jobs",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_pricing

TOOL

Get service pricing information including base prices, deposit requirements, and plan details.

Input Parameters

ParameterTypeRequiredDescription
serviceTypestringoptionalService type slug (optional — returns all if omitted)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "get_pricing",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_call_transcript

TOOL

Retrieve the transcript and metadata for a specific AI call by call log ID. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
callIdstringrequiredCall log ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "get_call_transcript",
    "arguments": {
      "callId": "<callId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_health

TOOL

Get system health status including database connectivity, circuit breaker states, and service metrics. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
No parameters required

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "get_health",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

calculate_dispatch_tco

TOOL

Calculate Total Cost of Ownership (TCO) and savings when migrating to DispatchNode. Ideal for deterministic comparisons against legacy competitors.

Input Parameters

ParameterTypeRequiredDescription
trucksnumberrequiredNumber of active trucks/technicians
current_softwarestringrequiredName of the legacy software used (e.g., 'ServiceTitan', 'Jobber', 'HouseCallPro')

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "calculate_dispatch_tco",
    "arguments": {
      "trucks": 1,
      "current_software": "<current_software>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

cancel_job

TOOL

Cancel an existing job. Customer tier requires phone number ownership validation. Operator tier can cancel any job.

Input Parameters

ParameterTypeRequiredDescription
jobIdstringrequiredJob ID to cancel
customerPhonestringoptionalCustomer phone for ownership validation (required for customer tier)
reasonstringoptionalCancellation reason

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "tools/call",
  "params": {
    "name": "cancel_job",
    "arguments": {
      "jobId": "<jobId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 8,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

update_job

TOOL

Update job status, priority, notes, or address. Creates audit trail. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
jobIdstringrequiredJob ID to update
statusenum: LEAD | QUOTED | SCHEDULED | IN_PROGRESS | COMPLETED | CANCELLEDoptionalNew status
priorityenum: normal | urgent | emergencyoptionalNew priority level
notesstringoptionalDispatch notes to append
serviceAddressstringoptionalUpdated service address

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 9,
  "method": "tools/call",
  "params": {
    "name": "update_job",
    "arguments": {
      "jobId": "<jobId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 9,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_customers

TOOL

Search and list customers with job count and LTV. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
searchstringoptionalSearch by name, company, restaurant/site, phone, or email
limitnumberoptionalMax results (default 20, max 100)
offsetnumberoptionalPagination offset

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 10,
  "method": "tools/call",
  "params": {
    "name": "list_customers",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 10,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

reschedule_job

TOOL

Move a job to a new date/time. Customer tier requires phone ownership validation.

Input Parameters

ParameterTypeRequiredDescription
jobIdstringrequiredJob ID to reschedule
newStartstringrequiredNew start datetime (ISO 8601)
newEndstringoptionalNew end datetime (ISO 8601, optional)
customerPhonestringoptionalCustomer phone for ownership validation (customer tier)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 11,
  "method": "tools/call",
  "params": {
    "name": "reschedule_job",
    "arguments": {
      "jobId": "<jobId>",
      "newStart": "<newStart>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 11,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_job_status

TOOL

Check job status and ETA by customer phone number. Returns the most recent active job.

Input Parameters

ParameterTypeRequiredDescription
customerPhonestringrequiredCustomer phone in E.164 format

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 12,
  "method": "tools/call",
  "params": {
    "name": "get_job_status",
    "arguments": {
      "customerPhone": "<customerPhone>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 12,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

assign_job

TOOL

Assign or reassign a technician/resource to a job. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
jobIdstringrequiredJob ID
resourceIdstringrequiredResource/technician ID to assign

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 13,
  "method": "tools/call",
  "params": {
    "name": "assign_job",
    "arguments": {
      "jobId": "<jobId>",
      "resourceId": "<resourceId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 13,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_customer

TOOL

Get full customer profile including contacts[], properties[] (sites), job history, LTV, and outstanding invoices. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
customerIdstringrequiredCustomer ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 14,
  "method": "tools/call",
  "params": {
    "name": "get_customer",
    "arguments": {
      "customerId": "<customerId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 14,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_invoices

TOOL

List invoices with optional status and date filters. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
statusenum: DRAFT | SENT | PAID | OVERDUEoptionalFilter by invoice status
customerIdstringoptionalFilter by customer ID
limitnumberoptionalMax results (default 20, max 100)
offsetnumberoptionalPagination offset

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 15,
  "method": "tools/call",
  "params": {
    "name": "list_invoices",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 15,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

create_invoice

TOOL

Create a new invoice for a job with line items. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
jobIdstringrequiredJob ID to invoice
lineItemsarrayrequiredArray of {description, amountCents}

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 16,
  "method": "tools/call",
  "params": {
    "name": "create_invoice",
    "arguments": {
      "jobId": "<jobId>",
      "lineItems": []
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 16,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_resources

TOOL

List technicians/resources with today's job count. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
typeenum: PERSON | TRUCK | ROOMoptionalFilter by resource type
activeOnlybooleanoptionalOnly show active resources (default true)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 17,
  "method": "tools/call",
  "params": {
    "name": "list_resources",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 17,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_resource_schedule

TOOL

Get a technician's job schedule for a date range. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
resourceIdstringrequiredResource ID
startDatestringrequiredStart date (ISO 8601)
endDatestringrequiredEnd date (ISO 8601)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 18,
  "method": "tools/call",
  "params": {
    "name": "get_resource_schedule",
    "arguments": {
      "resourceId": "<resourceId>",
      "startDate": "<startDate>",
      "endDate": "<endDate>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 18,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_dashboard_stats

TOOL

Get business performance summary for the current billing period. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
No parameters required

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 19,
  "method": "tools/call",
  "params": {
    "name": "get_dashboard_stats",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 19,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_usage_summary

TOOL

Get AI minutes usage, allowance, and overage status. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
No parameters required

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 20,
  "method": "tools/call",
  "params": {
    "name": "get_usage_summary",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 20,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_business_info

TOOL

Get business hours, location, contact info, and service area. Customer tier gets public info; operator tier gets full config.

Input Parameters

ParameterTypeRequiredDescription
No parameters required

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 21,
  "method": "tools/call",
  "params": {
    "name": "get_business_info",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 21,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

update_customer

TOOL

Update customer name, email, or company name. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
customerIdstringrequiredCustomer ID
namestringoptionalNew name
emailstringoptionalNew email
companyNamestringoptionalNew company name

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 22,
  "method": "tools/call",
  "params": {
    "name": "update_customer",
    "arguments": {
      "customerId": "<customerId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 22,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

send_invoice

TOOL

Email an invoice to the customer with payment link. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
invoiceIdstringrequiredInvoice ID to send

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 23,
  "method": "tools/call",
  "params": {
    "name": "send_invoice",
    "arguments": {
      "invoiceId": "<invoiceId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 23,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_service_types

TOOL

List all service types with full admin detail. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
includeInactivebooleanoptionalInclude inactive services (default false)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 24,
  "method": "tools/call",
  "params": {
    "name": "list_service_types",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 24,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

update_service_type

TOOL

Update service pricing, duration, or status. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
serviceSlugstringrequiredService type slug
priceBaseCentsnumberoptionalNew base price in cents
durationMinsnumberoptionalNew duration in minutes
depositCentsnumberoptionalNew deposit amount in cents
isActivebooleanoptionalEnable/disable this service

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 25,
  "method": "tools/call",
  "params": {
    "name": "update_service_type",
    "arguments": {
      "serviceSlug": "<serviceSlug>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 25,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_locations

TOOL

List branch locations with address, phone, and widget status. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
No parameters required

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 26,
  "method": "tools/call",
  "params": {
    "name": "list_locations",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 26,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_fleet_availability

TOOL

Check the availability of fleet units by date and unit type. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
startDatestringrequiredStart date (ISO 8601)
endDatestringrequiredEnd date (ISO 8601)
unitTypestringoptionalFleet unit type (e.g. 'Standard Unit')

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 27,
  "method": "tools/call",
  "params": {
    "name": "get_fleet_availability",
    "arguments": {
      "startDate": "<startDate>",
      "endDate": "<endDate>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 27,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

calculate_route_impact

TOOL

Evaluate if a new job fits into an existing driver's route. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
resourceIdstringrequiredDriver Resource ID
jobLatnumberrequiredNew job latitude
jobLngnumberrequiredNew job longitude
durationMinsnumberrequiredEstimated service duration in minutes

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 28,
  "method": "tools/call",
  "params": {
    "name": "calculate_route_impact",
    "arguments": {
      "resourceId": "<resourceId>",
      "jobLat": 1,
      "jobLng": 1,
      "durationMins": 1
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 28,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

spawn_job_agent

TOOL

Spawn an autonomous JobAgent to manage a job's full lifecycle — negotiation, quoting, scheduling, notifications, and invoicing. Use this when the customer confirms they want to book.

Input Parameters

ParameterTypeRequiredDescription
customerPhonestringrequiredCustomer phone in E.164 format
customerNamestringoptionalCustomer's full name
customerEmailstringoptionalCustomer email (optional)
serviceAddressstringrequiredDelivery/service address
requestedDatestringrequiredRequested date (YYYY-MM-DD)
unitsnumberoptionalNumber of units requested (default 1)
serviceTypestringoptionalService type (e.g. 'unit-dropoff', 'weekly-service')
unitTypestringoptionalUnit type (e.g. 'standard', 'ada', 'handwash')
sourceenum: VOICE | WIDGET | SMS | MANUALoptionalHow the request originated

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: customer
Requestjson
{
  "jsonrpc": "2.0",
  "id": 29,
  "method": "tools/call",
  "params": {
    "name": "spawn_job_agent",
    "arguments": {
      "customerPhone": "<customerPhone>",
      "serviceAddress": "<serviceAddress>",
      "requestedDate": "<requestedDate>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 29,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_contacts

TOOL

List CRM contacts for a customer. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
customerIdstringrequiredCustomer ID
includeArchivedbooleanoptionalInclude archived contacts (default false)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 30,
  "method": "tools/call",
  "params": {
    "name": "list_contacts",
    "arguments": {
      "customerId": "<customerId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 30,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_contact

TOOL

Get a single customer contact by ID. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
contactIdstringrequiredContact ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 31,
  "method": "tools/call",
  "params": {
    "name": "get_contact",
    "arguments": {
      "contactId": "<contactId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 31,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

create_contact

TOOL

Create a contact on a customer. Optionally set as primary (syncs denormalized Customer fields). (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
customerIdstringrequiredCustomer ID
firstNamestringrequiredContact first name
lastNamestringoptionalContact last name
rolestringoptionalRole (e.g. Decision Maker, Site Manager)
phonestringoptionalPrimary phone (E.164)
emailstringoptionalPrimary email
isPrimarybooleanoptionalMark as primary contact
notesstringoptionalNotes

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 32,
  "method": "tools/call",
  "params": {
    "name": "create_contact",
    "arguments": {
      "customerId": "<customerId>",
      "firstName": "<firstName>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 32,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

update_contact

TOOL

Update a customer contact. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
contactIdstringrequiredContact ID
firstNamestringoptional
lastNamestringoptional
rolestringoptional
phonestringoptional
emailstringoptional
isPrimarybooleanoptional
notesstringoptional

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 33,
  "method": "tools/call",
  "params": {
    "name": "update_contact",
    "arguments": {
      "contactId": "<contactId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 33,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_properties

TOOL

List customer sites/properties. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
customerIdstringrequiredCustomer ID
includeArchivedbooleanoptionalInclude archived sites (default false)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 34,
  "method": "tools/call",
  "params": {
    "name": "list_properties",
    "arguments": {
      "customerId": "<customerId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 34,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_property

TOOL

Get a customer site/property by ID. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
propertyIdstringrequiredProperty ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 35,
  "method": "tools/call",
  "params": {
    "name": "get_property",
    "arguments": {
      "propertyId": "<propertyId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 35,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

create_property

TOOL

Create a customer site/property. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
customerIdstringrequiredCustomer ID
namestringrequiredSite name (e.g. Main Office)
addressstringrequiredFull street address
externalIdstringoptionalStore / location number
notesstringoptional
addressLatnumberoptional
addressLngnumberoptional

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 36,
  "method": "tools/call",
  "params": {
    "name": "create_property",
    "arguments": {
      "customerId": "<customerId>",
      "name": "<name>",
      "address": "<address>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 36,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

update_property

TOOL

Update a customer site/property. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
propertyIdstringrequiredProperty ID
namestringoptional
addressstringoptional
externalIdstringoptional
notesstringoptional
addressLatnumberoptional
addressLngnumberoptional

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 37,
  "method": "tools/call",
  "params": {
    "name": "update_property",
    "arguments": {
      "propertyId": "<propertyId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 37,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_quotes

TOOL

List quotes with optional status/customer filters. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
statusenum: DRAFT | SENT | VIEWED | APPROVED | REJECTED | EXPIREDoptionalFilter by status
customerIdstringoptionalFilter by customer
limitnumberoptional
offsetnumberoptional

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 38,
  "method": "tools/call",
  "params": {
    "name": "list_quotes",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 38,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_quote

TOOL

Get a quote with line items and customer. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
quoteIdstringrequiredQuote ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 39,
  "method": "tools/call",
  "params": {
    "name": "get_quote",
    "arguments": {
      "quoteId": "<quoteId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 39,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

create_quote

TOOL

Create a DRAFT quote with line items. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
customerIdstringrequiredCustomer ID
lineItemsarrayrequiredArray of {description, qty, unitPriceCents, totalCents?}
taxCentsnumberoptional
jobIdstringoptional
notesstringoptional
clientNotesstringoptional
validUntilstringoptionalISO 8601 expiry

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 40,
  "method": "tools/call",
  "params": {
    "name": "create_quote",
    "arguments": {
      "customerId": "<customerId>",
      "lineItems": []
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 40,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_leads

TOOL

List pipeline leads (LeadSource). (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
statusstringoptionalFilter: NEW, CONTACTED, QUALIFIED, CONVERTED/won, LOST
searchstringoptionalSearch name/phone/email/company
limitnumberoptional
offsetnumberoptional

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 41,
  "method": "tools/call",
  "params": {
    "name": "list_leads",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 41,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_lead

TOOL

Get a single lead by ID. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
leadIdstringrequiredLead ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/call",
  "params": {
    "name": "get_lead",
    "arguments": {
      "leadId": "<leadId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 42,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

convert_lead

TOOL

Convert a lead to a customer (creates customer if needed, marks CONVERTED). (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
leadIdstringrequiredLead ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 43,
  "method": "tools/call",
  "params": {
    "name": "convert_lead",
    "arguments": {
      "leadId": "<leadId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 43,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_agreements

TOOL

List maintenance agreements. Requires agreements module. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
statusstringoptionalFilter by agreement status
customerIdstringoptional
limitnumberoptional
offsetnumberoptional

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 44,
  "method": "tools/call",
  "params": {
    "name": "list_agreements",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 44,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_agreement

TOOL

Get a maintenance agreement with coverage lines. Requires agreements module. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
agreementIdstringrequiredAgreement ID

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 45,
  "method": "tools/call",
  "params": {
    "name": "get_agreement",
    "arguments": {
      "agreementId": "<agreementId>"
    }
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 45,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

list_compliance_forms

TOOL

List compliance form templates (no PDF generation). Requires compliance module. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
activeOnlybooleanoptionalOnly active forms (default true)
limitnumberoptional
offsetnumberoptional

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 46,
  "method": "tools/call",
  "params": {
    "name": "list_compliance_forms",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 46,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

get_compliance_form

TOOL

Get a compliance form schema by formId or templateId. Requires compliance module. (Requires operator API key)

Input Parameters

ParameterTypeRequiredDescription
formIdstringoptionalComplianceForm ID
templateIdstringoptionalStable template key (e.g. nfpa-96-cert)

Response Fields

FieldTypeDescription
resultobjectTool-specific JSON payload (stringified in content[0].text)
tierstringAccess tier: operator
Requestjson
{
  "jsonrpc": "2.0",
  "id": 47,
  "method": "tools/call",
  "params": {
    "name": "get_compliance_form",
    "arguments": {}
  }
}
Responsejson
{
  "jsonrpc": "2.0",
  "id": 47,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{ /* tool result */ }"
      }
    ]
  }
}

Error Codes

CodeNameHTTPDescription
-32700Parse Error400Invalid JSON was received. Check your request body formatting.
-32600Invalid Request400The JSON is valid but not a valid JSON-RPC 2.0 request. Must include jsonrpc: '2.0' and a method field.
-32601Method Not Found200The requested method does not exist. Valid methods: initialize, tools/list, tools/call.
-32602Invalid Params200Unknown tool name passed to tools/call, or missing required parameters for a tool.
-32603Internal Error200Server-side error during tool execution (e.g. database timeout, validation failure).
-32001Authentication Error401Missing or invalid auth. Send Authorization: Bearer dnk_... (operator) or X-Org-Slug: <slug> (customer).
-32000Rate Limited429Customer tier rate limit exceeded. 30 requests/min or 10 bookings/hour per IP.
Error Response Examplejson
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "Invalid or revoked API key"
  }
}

SDK Examples

The MCP endpoint works with any HTTP client. Here are examples in popular languages:

curl (Customer — no API key)bash
# Customer tier: use X-Org-Slug (found in <link> tag on client site)
curl -X POST https://www.dispatchnode.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "X-Org-Slug: eventrestroomrentals" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "check_availability",
      "arguments": {
        "startDate": "2026-04-15",
        "endDate": "2026-04-16"
      }
    }
  }'
curl (Operator — full access)bash
# Operator tier: use Bearer token for all tools
curl -X POST https://www.dispatchnode.com/api/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer dnk_your_api_key_here" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
  }'
Pythonpython
import requests

BASE_URL = "https://www.dispatchnode.com/api/mcp"
API_KEY = "dnk_your_api_key_here"

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {API_KEY}"
}

# List available tools
response = requests.post(BASE_URL, json={
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/list"
}, headers=headers)

tools = response.json()["result"]["tools"]
print(f"Available tools: {[t['name'] for t in tools]}")

# Book a job
response = requests.post(BASE_URL, json={
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
        "name": "book_job",
        "arguments": {
            "customerName": "Jane Doe",
            "customerPhone": "+15559876543",
            "serviceAddress": "456 Oak Ave, Houston, TX",
            "scheduledStart": "2026-04-16T14:00:00Z"
        }
    }
}, headers=headers)

import json
result = json.loads(response.json()["result"]["content"][0]["text"])
print(f"Job booked: {result['jobId']}")
Node.js / TypeScripttypescript
const BASE_URL = "https://www.dispatchnode.com/api/mcp";
const API_KEY = "dnk_your_api_key_here";

async function mcpCall(method: string, params?: object) {
  const res = await fetch(BASE_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: Date.now(),
      method,
      params,
    }),
  });
  return res.json();
}

// List tools
const { result } = await mcpCall("tools/list");
console.log("Tools:", result.tools.map((t: { name: string }) => t.name));

// Check availability
const avail = await mcpCall("tools/call", {
  name: "check_availability",
  arguments: {
    startDate: "2026-04-15",
    endDate: "2026-04-16",
  },
});
const data = JSON.parse(avail.result.content[0].text);
console.log(`${data.existingBookings} existing bookings`);
Claude Desktop (mcp config)json
{
  "mcpServers": {
    "dispatchnode": {
      "url": "https://www.dispatchnode.com/api/mcp",
      "transport": "streamable-http",
      "headers": {
        "Authorization": "Bearer dnk_your_api_key_here"
      }
    }
  }
}

Discovery

MCP clients can discover the DispatchNode server through two mechanisms:

1. Well-Known Endpoint

Standard RFC 8414 / RFC 9728 discovery at the well-known URL:

GET https://www.dispatchnode.com/.well-known/mcp.json

2. Widget-Injected Link Tag

When the DispatchNode widget is embedded on a client site, it automatically injects a <link> tag into the host page for white-label discovery:

<link rel="mcp-server" href="https://dispatchnode.com/api/mcp" data-org-slug="eventrestroomrentals" data-tools="book_job,check_availability,get_pricing" data-auth="none" data-auth-header="X-Org-Slug: eventrestroomrentals" data-discovery="https://dispatchnode.com/.well-known/mcp.json" />

Rate Limits & Best Practices

LimitValue
Customer: requests/min30 per IP
Customer: bookings/hour10 per IP
Operator: requests/minUnlimited
Request body size1 MB
Max results (list_jobs)100 per page
Timeout30 seconds

Best Practices

Call get_health before a batch of operations to verify the system is healthy.
Use check_availability before book_job to avoid scheduling conflicts.
Always check for error responses — tool calls return errors in the JSON-RPC error field, not HTTP status codes.
Use monotonically increasing IDs for JSON-RPC request tracking.
Store the API key securely — never in client-side code or public repos.
Each API key is scoped to one org. Use separate keys per environment (dev/staging/prod).

© 2026 DispatchNode