This article is a technical reference for developers building an integration against LettrLabs inbound webhooks. It assumes you've already created a webhook connection and wired it to an action as described in the Setup Guide above.
How a request flows through LettrLabs
Your system sends an HTTP
POSTwith a JSON body to your webhook's URL.LettrLabs checks authentication (if you enabled it), then stores the raw request as an event and immediately returns a response — processing happens asynchronously after that.
For each action configured on that connection: if the action expects an array of records, LettrLabs first pulls the array out of your payload (only needed if your payload isn't already a single record); then, if you added filters, LettrLabs checks whether this payload passes them; then, if you configured field mapping, your raw fields are translated into the shape LettrLabs expects; finally the mapped data is routed based on the action's type — into a mail send, a radius mail search, or a conversion/lead record.
Endpoint and request format
Method / URL:
POSTto the unique URL shown when you created the connection, e.g.https://app.lettrlabs.com/api/webhooks/<webhook-guid>.Body: JSON. The exact shape only needs to match one of the field references below if you haven't configured field mapping for that action — with mapping configured, your source system's own JSON shape is fine, since LettrLabs translates it.
Authentication
OpenAPI Key (if enabled on the connection): include header
X-API-KEY: <your Open API key>. The key must belong to the same LettrLabs account that owns the webhook.HMAC-SHA256 signature (if enabled on the connection): compute an HMAC-SHA256 of the exact raw request body bytes using the secret shown when you clicked Generate Secret, and send it in one of these headers:
X-Signature-256,X-Hub-Signature-256,X-Signature, orX-Hub-Signature. The signature can be hex-encoded (64 characters) or base64-encoded, and may optionally be prefixed withsha256=(e.g.sha256=<signature>).
If neither option is enabled, the endpoint accepts unauthenticated requests — enable at least one before sending real production data.
Responses
200 { "status": "success" }— the event was received (and, once processed, ran successfully or is queued to).200 { "status": "filtered" }— received, but it didn't match a configured filter, so no action ran.401 { "status": "authenticationfailed" }— missing or invalid API key / signature.500 { "status": "failed" }— an unexpected error occurred while processing.
A connection that has been deleted, or is inactive, responds with a plain 200 message telling the caller to unsubscribe — build your integration to stop retrying if you ever see a non-JSON response like this.
Field reference: Mail to Recipients (Integration Order)
This is the shape LettrLabs needs once your payload has been mapped (or matches natively) for a Mail to Recipients action — one recipient per request.
Name:
FirstName,LastName, optionalSalutation, optionalToOrganization. A first and last name are effectively required — nearly every mail template's merge fields depend on them, and a recipient missing fields your chosen template needs will be rejected.Address (choose one): a full address in
Address1alone, or the split fieldsAddress1,Address2,City,State,ZipCode,Country. The address must validate against LettrLabs' address-verification step or the recipient is rejected with an error.Custom fields (optional):
Custom1throughCustom6, plus up to six variable image URLs (Image1–Image6) for templates using mail-merge images.Other optional fields:
Email,BirthDay,Anniversary,QrUrl(a custom QR destination for this recipient).Return-address override (optional, all-or-nothing):
ReturnFirstName/ReturnLastName(must be sent together, not one without the other),ReturnOrganization,ReturnTitle, andReturnAddress1/ReturnAddress2/ReturnCity/ReturnState/ReturnZip(if you send any return-address field,ReturnAddress1,ReturnCity,ReturnState, andReturnZipare all required together —ReturnAddress2stays optional). Sending a partial override is rejected.
Duplicate recipients (based on your account's resend window) and addresses on your Do Not Mail list are silently rejected rather than mailed twice or against a suppression.
Field reference: Radius Mail
This is the shape LettrLabs needs for a Radius Mail action — it searches for neighbors around a "pin" address and mails them.
Name (optional): a label for the search/order.
Addresses (required, a list — typically one pin address per request):
Address1— required; a full address, or the first line if you're splitting it out.Address2,City,State,Zip— optional ifAddress1is a full address.DesiredCount— required; how many nearby recipients to find and mail.
Property filters (optional):
OwnerOrRenterFilter(Owner / Renter / All),PropertyTypeFilter(SingleFamily / Other / All), and min/max range filters forHouseHoldIncomeFilter,LengthOfResidenceFilter(in years, 0–15),YearBuiltFilter(1900–2000), andHomePriceFilter— each snaps to the nearest supported bucket rather than an exact bound.MultiUse (optional): allow the same recipients to be reused across multiple radius searches.
Using property filters narrows who qualifies, but can push recipients outside the immediate neighborhood — which weakens the hyper-local "your neighbor just had this done" effect radius mail relies on.
Field reference: Conversion / Lead (attribution)
Conversion and Lead actions both accept the same shape — either a single object or a JSON array of objects in one request.
Name:
FirstName,LastName,FullName, and/orBusinessName.Primary / Secondary address (each optional, same shape):
FullAddress, orAddress1,Address2,City,State,ZipCode,Country.Contact:
PrimaryEmail/SecondaryEmail,PrimaryPhoneNumber/SecondaryPhoneNumber.Revenue (optional): send as a string — currency symbols, commas, and spaces are all accepted (e.g.
$1,250.75); if omitted or blank it defaults to0.EventDate (optional): when the conversion happened. Accepts ISO 8601 (
2025-12-25T15:30:00Z), date-only (2025-12-25), US-style (12/25/2025), or long-form (December 25, 2025); if omitted or unparseable, it defaults to the time LettrLabs processes the event.Identifiers (optional):
OrderId,StoreId,CustomerId,UniqueId,CrmId,CouponCode.Type (optional): a free-text label for the conversion.
Send at least one field LettrLabs can match against a mailed recipient — an address, email, phone number, or coupon code — or the conversion can't be attributed to a campaign.
Filtering, mapping, and deduplication
Field mapping: configured per action in the setup UI (Step 5 of the Setup Guide) — translates your raw payload's field names into the LettrLabs fields above.
Record selector: if your webhook sends a batch and the records live inside a nested array in your JSON, the action can be configured to pull that array out and process each item separately.
Inbound filters: conditions evaluated against the incoming (mapped) fields — for example, only proceed when a status field equals a specific value, or a numeric field crosses a threshold. Events that don't pass are marked
filtered, not treated as errors.Unique Id + Run Once: pick a field that uniquely identifies a record (e.g. an order ID) and enable Run Once to make sure LettrLabs only acts on that specific record a single time, even if your system re-sends the same event.
Monitoring delivery
The History tab on the Active Webhooks page lists every event your connection received. An event's status is one of: Received (accepted, awaiting processing), Processing, Success, Filtered Out, Authentication Failed, Mapping Error, Invalid Payload, or Failed. Opening an event shows the status of each individual action that ran against it — Pending, Processing, Success, Failed, DeDuplicated (blocked by Run Once), FilteredOut, MappingError, MissingUniqueId (Run Once is on but no unique value could be found in the payload), or Skipped (the action was turned off between the event arriving and being processed).
