Stitch developer guide
For: the engineers wiring Beeline’s systems to Stitch. One page that says what gets built, by event, in the order it pays off, with a link to the full contract for each piece. The per-event pages are the contracts; this page is the map.
Stitch is built around events, not systems. It does not know which system will send a given event, when it fires, or whether a middleware sits in between — it sees a key, which names the system the owner issued it to, and a payload. So this guide is organised by event, and the table at the end says who we think owns each one today. If that is you, build it; if it turns out to be a middleware or another team, the contract is the same.
Environment, today: dev only. This guide and the contracts are published at https://stitchdocs.beeline.team; the API reference there covers every endpoint named below.
| URL | |
|---|---|
| Collector (every integration endpoint, the SDK) | https://stitch-collector-dev.magic-blocks.workers.dev |
| App (the screens, the exports) | https://stitch-app-dev.magic-blocks.workers.dev |
Production will put the collector on a first-party host per brand
(t.makeabeeline.com, t.beelineequitynow.com); nothing in the contracts
changes, only the hostname.
Every server-to-server call carries Authorization: Bearer <key>. There is
one key per emitting system, issued by the owner and named after whatever
actually sends — ask MagicBlocks; keys are never sent over chat. The system a
key belongs to is recorded on every row it creates, so a key for a middleware
says “middleware”, not the name of the system behind it. A missing or wrong
key is a 401 with no detail. Three names are Stitch’s own and cannot be a
key: stitch, manual, manual_spread. The browser’s endpoints (/v1/collect,
/v1/consent, /v1/decorate, /sdk.js) need none. Full detail:
the provisioning runbook (internal).
Two rules apply everywhere: the lifecycle endpoints take an idempotency key
and re-sending it is a harmless 200; send what you have now and more later —
no payload needs to be complete. See README.md.
What gets built, by event
Section titled “What gets built, by event”In the order it pays off.
1. A person becomes known → POST /v1/identify
Section titled “1. A person becomes known → POST /v1/identify”The moment a contact is created from a web form, chat or call, send the
visitor’s anon_id (read server-side from the _bid cookie) with the
contact’s id. That binds the entire prior browsing history to the person in
one deterministic call — the single highest-leverage integration. Send it
again on every authenticated sign-in; it is idempotent and repairs drift.
→ identity.md
2. A lead is created or changes status → POST /v1/conversion with event
Section titled “2. A lead is created or changes status → POST /v1/conversion with event”The lead’s created event with the real creation time (it becomes the
attribution anchor), the contact id, vendor_source, cost_cents, and
attrs.submission_id from the form’s hidden field so the pixel’s event and
Stitch’s are one event to the platform. Later status events as they happen.
→ lead-events.md
3. A loan starts, moves and funds → POST /v1/conversion with stage
Section titled “3. A loan starts, moves and funds → POST /v1/conversion with stage”Every stage you have, when you have it, with the loan’s attributes as they
stand: loan_amount, property_value, the stated credit_range/credit_band,
fico once pulled, app_type, product, occupancy; lead_external_id on
the first event; realised gross_revenue at funding; the current amount on
later events when the file changes it. Stitch scores the application on
ingest, sends the conversions, and exports the final figures for the model’s
refit. → loan-stages.md
4. The website → the SDK, the submission id, consent, tracking templates
Section titled “4. The website → the SDK, the submission id, consent, tracking templates”- Load the SDK from the collector: one script tag, no configuration beyond the host. It records page views, sessions, click ids, the ad ids from the tracking templates and the vendor pixels’ cookies, and honours Global Privacy Control on its own. → web-sdk.md
- On the lead form, write
window.stitch.submission()into a hidden fieldstitch_submission_idand fire the Meta/TikTok pixels with the same id — guarded, as the page shows. → web-sdk.md §3a - Call
window.stitch.consent({...})from the CMP’s change callback. → consent.md - Media buying: set the tracking templates per platform so every paid click
lands with its click id, the ad ids, and the campaign name in
utm_campaign. → tracking-templates.md
5. An application’s value is wanted now → POST /v1/score
Section titled “5. An application’s value is wanted now → POST /v1/score”When the application sections are complete, post the five fields the borrower
entered and report conversion_value as the value of the application
conversion you report to Google. Same body and answer as the EV Worker’s
/score. Do not call it
again with updated figures: the value is computed from what the borrower
entered and corrected afterwards only by Stitch’s own restatements (the pulled
score, the realised revenue, a dead end).
→ application-value.md, outbound.md
6. A session happens outside the browser → POST /v1/session
Section titled “6. A session happens outside the browser → POST /v1/session”Portal sessions and agent sessions, with the page’s anon_id when the session
began on one of our pages, and goal events through /v1/collect. These
convert; they never acquire. → sessions.md
7. Someone says how they heard about us → POST /v1/declared
Section titled “7. Someone says how they heard about us → POST /v1/declared”On the lead’s attrs, or directly from a form handler, a loan officer’s tool, or a voice agent. → declared-source.md
8. Ops and media buying
Section titled “8. Ops and media buying”- Call attribution through Twilio. → twilio-dni.md
- Ad spend beside value. → spend.md
- Conversions back to the platforms — Google, Meta, TikTok, LinkedIn, Microsoft, Taboola, Outbrain, a signed webhook (Zapier) — each a row to enable and credentials to set; what is sent, matched on, excluded and restated. → outbound.md
Who most likely owns each event today
Section titled “Who most likely owns each event today”Our best guess, written down so it can be corrected. Nothing in a contract depends on it being right.
| Event | Today, probably | Could equally be |
|---|---|---|
| A person becomes known | the form handler or CRM at contact creation; the portal at sign-in; the agent when it learns an identity | a middleware that fronts any of them |
| Lead events | the CRM (Relcu) | a middleware in front of it, or whatever replaces it |
| Loan stages and value | the loan origination system (Vesta) | a middleware, an export job, a data platform that already mirrors it |
| Application value | the application’s backend (makeabeeline.com’s app) | a middleware that fronts the application |
| Sessions outside the browser | the portal’s backend; the agent platform (MagicBlocks) | a middleware |
| Declared source | whoever asks: the lead form, the loan officers, the agent | — |
| Spend | media buying / ad ops | an agency’s reporting |
Reading it back
Section titled “Reading it back”- The screens: sign in at the app URL with your work email; a code is emailed. Access levels and how people are added: the access runbook (internal).
- The predictions export for the value model’s refit:
GET /api/export/predictions?since=YYYY-MM-DDon the app, with the export token. → application-value.md
Verifying
Section titled “Verifying”Every page ends with a curl you can paste against dev; the same commands
run in scripts/smoke-*.sh. Test rows are real rows — use an obvious prefix
on ids so they can be excluded later.