The Doozer Brainlive from the knowledge bundle · v2.2.618 · 2026-09-13 17:15 ETall pages · one page

Thanks.io Connector (direct mail, two-way)

systems/thanksio.md · System · thanksio, direct-mail, postcards, radius, targeting, webhooks, claim-codes, prospector, intelligence

unverified: no trust signals recorded yet

How Doozer sends physical mail via Thanks.io and feeds the results back into intelligence — claim postcards, radius audience buying that reverse-engineers new sites, and delivery/scan webhooks.

Thanks.io Connector

Thanks.io is a direct-mail API (postcards, letters, notecards) with radius audience buying and QR/delivery webhooks. Doozer uses it both ways so every send and every response compounds into the intelligence layer. Grounded in the real API: base https://api.thanks.io/api/v2, auth Authorization: Bearer <key>. Engine: includes/thanksio.php. Config-free, self-creating tables, portable.

The three loops

  1. Mail the businesses we built (claim). thanksIoMailClaim($businessId)
  2. mints a claim code + doozer.link QR (claim-codes) and sends a postcard to the business address carrying that QR and a warm message. Receiving it proves the address; scanning/entering claims the listing. Doozer+ "pay first, snail mail, claim" verification uses the same path (plus_verify).

  1. Radius targeting → new site inventory (reverse-engineering).
  2. thanksIoBuyRadiusSearch(address, postal, count, {record_types, append_data}) buys 1–10,000 real addresses around a point ($0.05/record, +$0.20 with phone/email append), filtered by record_types: all, onlybusinesses, newbusiness, newhomeowner, renters, absenteeowner, likelytomove, highnetworth, retired, and more. thanksIoIngestRadiusTargets(listId) pulls the records into thanksio_targets; thanksIoBuildFromTargets() resolves each business record to a Google Place (placesSearchBest) and materializes a Doozer site (resolvePlaceToEcosystem). The mailing list becomes site inventory — which then earns its own claim postcard. Full circle.

  1. Webhooks back into intelligence. ?e=thanksio_webhook (gated by a shared
  2. secret in the URL — Thanks.io sends no signature) ingests order.status_update / order_item.delivered / scans.scan_update into thanksio_events, mirrors status onto the matching thanksio_sends row, and pings Comms: delivered = the address is reachable (the proof-of-address precondition), scan = the owner engaged before claiming (a demand signal for the Demand Ledger).

Tables

Safety

Spend is real and irreversible, so: every send DEFAULTS TO PREVIEW (Thanks.io returns an estimate, no charge) unless live=1; radius buys return a cost estimate unless confirm=1; build-from-targets is bounded per call. Operator- triggered only. Cost logged on every row ([[feedback_api_costs]]).

Cost-units bug FIXED (v2.2.409): Thanks.io returns authorization_total / leads_fee ALREADY in cents (114 = $1.14 for a 4x6, 1 recipient); the send path (thanksIoSendPostcard) was doing round(value * 100) → stored 100× too high (11400 for a $1.14 card). Dropped the *100; dz postcard do=fixcosts re-derives historical thanksio_sends rows from raw meta.response.authorization_total. Previews (proof images) live at response.data.previews = [front, handwriting back] S3 URLs; persisted to postcard_designs.proof_urls for the admin lightbox.

Live postcard tracking (v2.2.407)

Delivery/scan/claim per send are read LIVE by postcardDesignLiveStats() ([[ai-postcards]]) from thanksio_sends + thanksio_events + shortlinks + claim_codes (never cached JSON). The webhook now also recomputes the linked postcard_designs.tracking on each delivered/scan event, so the admin "Sent & performance" view stays fresh without a manual Refresh.

Ops + setup

Back-of-card copy + response levers (v2.2.392)

The front is the Factory image; the BACK is where direct-mail response is won. thanksIoClaimMessageVariants($bizName,$code,$opts) returns warm / leads / curious variants, personalized with the town, no em-dashes. The message never spells out the claim code or the doozer.link URL (v2.2.405): cursive handwriting makes codes/URLs hard to read, and a code is already a friction point, so the back POINTS to them instead: "Scan the QR code, or use the claim code printed on the front of this card." Code + URL live only where they're legible: the front. Greeting frames the business as the OBJECT, not a salutation: "Hi, we built Powell Flooring a real website..." (warm "you / yours"), not "Hi Powell Flooring, we built you...". thanksIoDefaultClaimMessage picks one (opts.variant). Operator levers (all platform_settings, flowed through thanksIoMailClaim): thanksio.handwriting_style_id (a handwritten back lifts response), thanksio.size (4x6 default; 6x9/6x11 stand out but need a matching front aspect), thanksio.message_variant. Multi-campaign: postcardCampaignMessage resolves the back copy per campaign (claim → these variants; other campaigns → their message_template with tokens).

Related: claim codes, shortlinks + QR, AI Postcards (campaigns + Factory + Theme Studio), the observed world (mail closes the CLAIM loop; radius feeds OBSERVE), Prospector / place-resolver.

Source-of-truth cache (read the real website)The /now surface and the dense directory — the app NearByMeNow already almost was