Integrating with Stitch
Stitch is Beeline’s cross-channel attribution system. It answers two questions that are usually conflated: who brought this person into our world, and who produced this loan. Those are separate ledgers and they are never summed.
This directory is one page per event the collector accepts, not one per system. Stitch does not know which system will send an event, or when, or through what — a CRM’s webhook, a loan origination system’s, a middleware in front of either, or a replacement for any of them. It sees a key, which names the system the owner issued it to, and a payload. Each page therefore describes the event: its payload, its idempotency, what Stitch does with it, and a smoke test; and names, as a guess, who most likely owns it today. New here? Start with the developer guide: what gets built, in the order it pays off, with the link to each contract.
New to the terminology? ../glossary.md explains every term this system uses in plain English — the two ledgers, the confidence ratings, and why “brand search” is treated differently from everything else.
These pages are also published at https://stitchdocs.beeline.team, with an API reference for every collector endpoint.
Base URL
Section titled “Base URL”https://stitch-collector-dev.magic-blocks.workers.devDevelopment only. Production hostnames will be t.makeabeeline.com and
t.beelineequitynow.com — one first-party collector per registrable domain,
which matters more than it looks (see web-sdk.md).
Every server-to-server call (/v1/identify, /v1/conversion, /v1/session,
/v1/score, and /v1/declared from a system) sends
Authorization: Bearer <your key>. The owner issues one key per emitting
system and names it after whatever actually sends. The browser’s endpoints
(/v1/collect, /v1/consent, /v1/decorate, /sdk.js) need none.
Read in this order
Section titled “Read in this order”Ordered by leverage, not by size. The first two are worth more than everything below them combined. “Emitted by” is our best guess at who owns the event today; the contract does not change if it is someone else.
| # | Event | Page | Emitted by (today, our guess) | What it unlocks | What breaks without it |
|---|---|---|---|---|---|
| 1 | A person becomes known | identity.md | the form handler or CRM at contact creation; the portal at sign-in; an agent | Bind-at-birth. Anonymous browsing history attaches to a real person deterministically | The last probabilistic step in the whole conversion path stays probabilistic. Anonymous history and the contact remain two islands |
| 2 | A lead is created or changes status | lead-events.md | whatever is the system of record for leads (today, probably the CRM) | The lead grain, its attribution anchor, the lead conversion to the ad platforms, the submission id that makes the pixel’s event and ours one | No leads to attribute; the platforms learn from form fills instead of leads |
| 3 | A loan starts, moves, funds | loan-stages.md | the loan origination system | Loan creation, stage transitions and realised revenue. This is the conversion object | There is nothing to attribute. Every report is empty |
| 3b | An application’s value is wanted now | application-value.md | the application’s backend | The application’s value, from the borrower’s own entry, reported to Google and restated as the loan’s truth arrives | Google bids on form fills; the application conversion carries no value |
| 4 | A page is viewed, a form is submitted | web-sdk.md, tracking-templates.md | the websites; media buying for the templates | Sessions, sources, click IDs, campaign and ad ids, the vendor pixels’ cookies, the submission id | Nothing upstream of the lead is known |
| 5 | A session happens outside the browser | sessions.md | the portal’s backend; the agent platform | Portal and agent sessions, goal events, the agent’s measurable lift | Agent contribution is invisible, and sessions the agent identifies are never bound |
| 6 | Someone says how they heard about us | declared-source.md | whoever asks the question | The one answer instrumentation cannot give, cross-tabbed against what was tracked | Phone, podcast and word of mouth look like “direct” |
| 7 | Someone refuses or consents | consent.md | the CMP, the SDK, a “Do Not Sell” link | A refusal that actually changes what is sent | Opt-outs are recorded nowhere that matters |
| 8 | A call comes in | twilio-dni.md | ops / Twilio | Call attribution, upgrading source certainty from tier E to tier C | Phone-in leads stay unattributed |
| 9 | A conversion goes back out | outbound.md | Stitch itself | Lead, application and funded value fed to ad platform bidding, restated as the truth arrives | The platforms optimise on leads instead of funded loans |
| 10 | Money is spent | spend.md | media buying / ad ops | Cost beside value: CAC, cost per funded loan, ROAS, and the spend that reached nothing | Every screen says what a channel produced and none can say what it cost |
Two rules that apply to every page
Section titled “Two rules that apply to every page”Idempotency is your safety net, so use it. /v1/conversion takes an
idempotency_key and /v1/session an external_session_ref; /v1/identify
is idempotent by nature. Re-sending the same key is a no-op that returns 200
instead of 202. Fire the same message a hundred times if your retry logic
wants to — it costs nothing and it is far safer than trying to send exactly
once.
Send what you have, send more later. No endpoint requires a complete
payload. Loan attributes in particular are versioned with validity windows, so
a property_status of tbd that later becomes identified is recorded as
both, with the transition measurable. Do not wait for complete data.
Two rules Stitch applies that you should know about
Section titled “Two rules Stitch applies that you should know about”AI and portal sessions convert; they do not acquire. Both are hard-classed
as nurture and can never take acquisition credit, whatever you send. The
agent harvests demand a channel already produced — if it could take credit it
would progressively cannibalise credit from every real channel, and the better
it performed the more it would distort the picture.
URL events are behavioural; the system of record is transactional. A
/thank-you page hit is evidence someone probably submitted a form. The lead
is whatever the system of record says it is. Stitch counts leads from the lead
event and uses page events only for funnel shape. The two are never summed and
never substituted, which is what stops the classic failure where the site
reports 400 conversions, the CRM’s own count is 340, and nobody can explain the gap.
Verifying your integration
Section titled “Verifying your integration”Every page ends with a curl you can paste. These are the same commands
scripts/smoke-*.sh runs in CI, so the guide cannot drift from what is
actually tested.
Getting help
Section titled “Getting help”Endpoint behaviour is defined by the tests in workers/collector/test/. If
this guide and those tests disagree, the tests are right and the guide is a
bug — please say so.
Every URL and the sign-in steps: the where-everything-is runbook (internal).