POST https://localedgemarketingco.com/api?action=import_lead
All API requests require authentication using a Bearer token in the Authorization header.
Authorization: Bearer YOUR_API_KEY_HEREContent-Type: application/jsonGetting Your API Key:
Rate Limits: API requests are limited to 100 requests per minute per API key.
Every response is JSON and follows one consistent shape. The success boolean tells you which envelope you received, and every response carries an api_version.
Success envelope:
{
"success": true,
"api_version": "1.0",
... endpoint-specific fields
}
Error envelope: every failure includes a stable, machine-readable code you can branch on in your integration. The human-readable error text may change over time; the code will not.
{
"success": false,
"api_version": "1.0",
"error": "Human-readable message",
"code": "MACHINE_CODE"
}
Error codes:
MISSING_REQUIRED_FIELD (400): a required field is absent or malformed (missing name, no identifier, or an invalid lead_id).UNAUTHORIZED (401): missing or invalid API key.API_KEY_DISABLED (403): the account behind this key is deactivated.LEAD_LIMIT_REACHED (403): your plan's lead limit is reached (import only).NOT_FOUND (404): no lead on your account matches the identifier.RATE_LIMIT_EXCEEDED (429): over 100 requests per minute; a retry_after value (in seconds) is included.INTERNAL_ERROR (500): unexpected server error. Safe to retry with backoff.Versioning: the current version is 1.0. Additive changes (new optional fields or new endpoints) keep the same major version and will not break existing integrations. Any breaking change to the wire contract is released under a new major version, so your integration keeps working unchanged. Read api_version if you need to detect which contract you received.
{
"name": "Jane Smith",
"email": "jane.smith@example.com",
"phone": "5551234567",
"source": "Zillow",
"tags": ["zillow", "buyer", "new"],
"addresses": [
{
"type": "home",
"street": "123 Main St",
"city": "Los Angeles",
"state": "CA",
"zip": "90001"
},
{
"street": "456 Oak Ave",
"city": "San Diego",
"state": "CA",
"zip": "92101"
}
],
"stage": "new",
"type": "buyer"
}
name and at least one of email or phonesource, tags, addresses (array, each with type (optional, defaults to OTHER), street, city, state, zip), stage, type, etc.
{
"success": true,
"api_version": "1.0",
"lead_id": "uuid-or-id-here",
"action": "created" // or "updated"
}
All errors follow the shared error envelope and the codes listed in Response Format & Versioning above. The two cases specific to importing:
400 Bad Request - Missing Required Fields:
{
"success": false,
"api_version": "1.0",
"error": "Missing required field: name",
"code": "MISSING_REQUIRED_FIELD"
}
403 Forbidden - Lead Limit Reached:
{
"success": false,
"api_version": "1.0",
"error": "Lead limit reached (500 of 500). Upgrade your plan to import more leads.",
"code": "LEAD_LIMIT_REACHED"
}
429 Too Many Requests - Rate Limit Exceeded:
{
"success": false,
"api_version": "1.0",
"error": "Rate limit exceeded. Maximum 100 requests per minute.",
"code": "RATE_LIMIT_EXCEEDED",
"retry_after": 60
}
You can use tools like Postman, cURL, Zapier, Make, or any programming language that supports HTTP requests.
curl -X POST "https://localedgemarketingco.com/api?action=import_lead" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY_HERE" \
-d '{
"name": "Jane Smith",
"email": "jane.smith@example.com",
"phone": "5551234567",
"source": "Zillow",
"tags": ["zillow", "buyer", "new"],
"addresses": [
{
"type": "home",
"street": "123 Main St",
"city": "Los Angeles",
"state": "CA",
"zip": "90001"
},
{
"street": "456 Oak Ave",
"city": "San Diego",
"state": "CA",
"zip": "92101"
}
],
"stage": "new",
"type": "buyer"
}'
POST https://localedgemarketingco.com/api?action=get_lead_status
Check what has happened to a lead you previously sent. Uses the same Bearer API key as the import endpoint.
Request Body: provide any one of these identifiers.
lead_id (the id returned by import_lead), oremail, orphone
{
"lead_id": "uuid-of-the-lead"
}
Sample Success Response:
{
"success": true,
"api_version": "1.0",
"lead": {
"lead_id": "uuid-or-id-here",
"name": "Jane Smith",
"stage": "Contacted",
"type": "Buyer",
"source": "Zillow",
"tags": ["zillow", "buyer"],
"created_at": "2026-07-23 14:07:57+00",
"updated_at": "2026-07-23 15:22:10+00"
}
}
Lead Not Found (404):
{
"success": false,
"api_version": "1.0",
"error": "Lead not found",
"code": "NOT_FOUND"
}
You can only look up leads that belong to your own account.
POST https://localedgemarketingco.com/api?action=partner_add_note
Record activity against a lead you previously sent, for example "customer replied on our platform" or "showing booked". This is append only: it adds to the lead timeline and never changes existing lead data.
Request Body: note plus any one of lead_id, email or phone.
{
"lead_id": "uuid-of-the-lead",
"note": "Customer replied on our platform and asked for a showing."
}
Sample Success Response:
{
"success": true,
"api_version": "1.0",
"lead_id": "uuid-or-id-here",
"note_id": 390878
}
404 NOT_FOUND if the lead does not exist on your account.POST https://localedgemarketingco.com/api?action=partner_list_leads
Pull your leads for reconciliation, or sync incrementally by passing updated_since. Results are ordered by most recently changed first, and only ever include leads on your own account.
Request Body: all fields optional.
{
"updated_since": "2026-07-01T00:00:00Z",
"stage": "New",
"limit": 50,
"offset": 0
}
updated_since: any parseable date or timestamp. Returns only leads changed at or after it.stage: optional stage filter (case insensitive).limit: defaults to 50, maximum 200.offset: defaults to 0. Page forward while has_more is true.Sample Success Response:
{
"success": true,
"api_version": "1.0",
"leads": [
{
"lead_id": "uuid-or-id-here",
"name": "Jane Smith",
"stage": "Contacted",
"type": "Buyer",
"source": "Zillow",
"tags": ["zillow", "buyer"],
"created_at": "2026-07-23 14:07:57+00",
"updated_at": "2026-07-23 15:22:10+00"
}
],
"count": 1,
"has_more": false,
"limit": 50,
"offset": 0
}
POST https://localedgemarketingco.com/api?action=partner_update_lead
Update a lead you previously sent as it moves along your pipeline. Whitelisted to stage and tags only: the lead's name, source and other curated fields are never changed. Tags are additive (add with tags, remove with remove_tags); stage is set directly.
Request Body: any one of lead_id, email or phone, plus at least one of stage, tags or remove_tags.
{
"lead_id": "uuid-of-the-lead",
"stage": "Contacted",
"tags": ["engaged", "hot"],
"remove_tags": ["cold"]
}
Sample Success Response:
{
"success": true,
"api_version": "1.0",
"lead": {
"lead_id": "uuid-or-id-here",
"name": "Jane Smith",
"stage": "Contacted",
"type": "Buyer",
"source": "Zillow",
"tags": ["engaged", "hot"],
"created_at": "2026-07-23 14:07:57+00",
"updated_at": "2026-07-28 09:15:00+00"
}
}
Returns 400 MISSING_REQUIRED_FIELD if no updatable field is provided, or 404 NOT_FOUND if the lead is not on your account.
POST https://localedgemarketingco.com/api?action=partner_list_lead_notes
Read the timeline notes on a lead you sent, newest first. Internal system notes are not included. This is the read counterpart to the add-note endpoint.
Request Body: any one of lead_id, email or phone, plus optional paging.
{
"lead_id": "uuid-of-the-lead",
"limit": 50,
"offset": 0
}
limit: defaults to 50, maximum 200.offset: defaults to 0. Page forward while has_more is true.Sample Success Response:
{
"success": true,
"api_version": "1.0",
"notes": [
{
"note_id": 390878,
"message": "Customer replied on our platform and asked for a showing.",
"type": "note",
"created_at": "2026-07-24 10:30:00+00"
}
],
"count": 1,
"has_more": false,
"limit": 50,
"offset": 0
}
POST https://localedgemarketingco.com/api?action=partner_opt_out_lead
Honor a do-not-contact request from your side. This suppresses the lead's phone and/or email so the account stops contacting them by SMS and email. It does not change the lead record.
Request Body: any one of lead_id, email or phone, plus an optional channel.
{
"lead_id": "uuid-of-the-lead",
"channel": "all"
}
channel: one of all (default), phone, or email.Sample Success Response: suppressed reports how many phone and email identifiers are now suppressed for this lead.
{
"success": true,
"api_version": "1.0",
"lead_id": "uuid-or-id-here",
"suppressed": {
"phone": 1,
"email": 1
}
}
Instead of polling, subscribe to events and have this CRM POST them to your server in real time. When a lead you own is created, changes stage, or gets a note, we send a signed JSON request to your registered URL. Webhooks use the same Bearer API key as the rest of the API.
secret (shown once).X-Webhook-Signature so you can verify it came from us.X-Webhook-Delivery.POST https://localedgemarketingco.com/api?action=partner_register_webhook
Request Body: url plus events (any of lead.created, lead.stage_changed, note.added).
{
"url": "https://your-server.com/webhooks/localedge",
"events": ["lead.created", "lead.stage_changed", "note.added"]
}
Sample Success Response (the secret is shown only here, so save it):
{
"success": true,
"api_version": "1.0",
"webhook_id": "uuid-here",
"secret": "64-hex-character-signing-secret",
"url": "https://your-server.com/webhooks/localedge",
"events": ["lead.created", "lead.stage_changed", "note.added"]
}
List: POST https://localedgemarketingco.com/api?action=partner_list_webhooks (no body). Returns your subscriptions; the secret is never returned again.
{
"success": true,
"api_version": "1.0",
"webhooks": [
{ "webhook_id": "uuid-here", "url": "https://your-server.com/webhooks/localedge", "events": ["lead.created"], "active": true, "created_at": "2026-07-29 17:00:00" }
],
"count": 1
}
Delete: POST https://localedgemarketingco.com/api?action=partner_delete_webhook with { "webhook_id": "uuid-here" }. Returns 404 NOT_FOUND if it is not yours.
Test: POST https://localedgemarketingco.com/api?action=partner_test_webhook with { "webhook_id": "uuid-here" }. We immediately send a signed webhook.test ping to your URL and report the HTTP status your endpoint returned, so you can confirm your receiver and signature check work.
{
"success": true,
"api_version": "1.0",
"webhook_id": "uuid-here",
"delivered": true,
"status_code": 200,
"error": null
}
Every delivery is a POST with a JSON body and these headers:
X-Webhook-Event: the event type (for example lead.created).X-Webhook-Delivery: a unique delivery id. Use it to de-duplicate retries.X-Webhook-Signature: sha256=<hmac> (see Verifying the Signature below).lead.created and lead.stage_changed (the latter also includes previous_stage):
{
"api_version": "1.0",
"event": "lead.stage_changed",
"lead_id": "uuid-here",
"name": "Jane Smith",
"stage": "Contacted",
"previous_stage": "New",
"type": "Buyer",
"source": "Zillow",
"occurred_at": "2026-07-29T17:37:25+00:00"
}
note.added:
{
"api_version": "1.0",
"event": "note.added",
"lead_id": "uuid-here",
"note_id": 390878,
"message": "Customer replied and asked for a showing.",
"note_type": "note",
"occurred_at": "2026-07-29T17:37:25+00:00"
}
Every delivery is signed so you can confirm it came from us and was not altered. The X-Webhook-Signature header is sha256= followed by the HMAC-SHA256 of the raw request body, keyed with your webhook secret. Recompute it and compare using a constant-time check.
// Node.js
const crypto = require("crypto");
const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(rawBody).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.header("X-Webhook-Signature")));
# PHP
$expected = "sha256=" . hash_hmac("sha256", $rawBody, $secret);
$ok = hash_equals($expected, $_SERVER["HTTP_X_WEBHOOK_SIGNATURE"]);
Reject any request whose signature does not match. Always hash the exact bytes you received, before any JSON parsing or reformatting.
X-Webhook-Delivery.occurred_at if ordering matters.action comes back as updated. New emails, phones, tags and addresses are added, while the existing name, stage, type and source are preserved so your import never overwrites work the agent has already done.OTHER.You can also create leads by sending an email to your CRM's lead inbox. The email parser supports the same fields as the API, using simple text patterns in the email body.
Address (HOME): 123 Main St, Springfield, IL, 62701. The type is optional and will default to OTHER if not provided.Phone:, Phone 2:, Email:, Email 2:, etc. for multiple values.Note:, Note 2:, etc. for multiple notes.Tags: tag1, tag2, tag3.Sample Email Body:
Name: Jane Smith
Stage: prospect
Type: seller
Tags: new, test, emailparser
Source: website
Address: 100 Main St, Springfield, IL, 62701
Address 2: 200 Oak Ave, Shelbyville, IL, 62565
Phone: 5551230001
Phone 2: 5551230002
Phone 3: 5551230003
Email: janesmith001@example.net
Email 2: contact.jane.smith@fakemail.org
Email 3: jsmith.random@nowhere.test
Note: This is a test note for Jane Smith.
Note 2: Second note for testing.
Note 3: Final test note.
user: {user email}
All fields are optional except name and at least one of email or phone. The parser will extract as much information as possible and send it to the API automatically.