docs.vin

Buy a car end to end

Search → offer → credit → F&I → out-the-door → e-contract → payments & escrow → title & registration → transport → delivery — every step a catalog capability, runnable against the sandbox world.

Buying a car is the estate's spine workflow: a saved search matches, an offer extends and accepts, credit prices the buyer, the F&I menu attaches, the out-the-door figure derives, the e-contract papers, money moves through escrow, the title work opens and the lien records, a carrier moves the unit, and the deal closes delivered. Under the journey-ownership ruling (2026-08-17), each step answers from its shared-world owner: the deal and offer doors from the car desk that reads the DealLifecycle and OfferFSM machines, the paper from the funding pipeline and the signing desk, the tag from the tag desk, the lien from the risk-money desk — and the journey keeps only its own pair, the F&I selection and the out-the-door derivation, whose every line is owned elsewhere (the valuation book's retail band, the title rail's fee estimate, the one documented menu).

The cast

This journey rides the curated world — deterministic, replayable, every payload provenance-labeled. One fleet exemplar stands at each position of the DealLifecycle arc, and the persona cast prices the buyer (identity is the trigger: first name, last name, zip). The full trigger register is at sandbox test triggers.

World keyRole in this journey
1FDEALFRESH000000The fresh quote: DealLifecycle QUOTED — search matched, offer extended.
1FDEALDESKED00000The desked deal: offer accepted, e-contract drafted — ready to paper.
1FDEALS1GNED00000The contracted deal: packet signed, escrow funded.
1FDEALFUNDED00000The funded deal: loan booked and funded — the lien records here.
1FDEALDEL1VERED00The delivered deal: temp tag issued, title pending.
1FDEALCL0SED00000The closed deal: title transferred, permanent plate on file.
1FDEALH0LD0000000The held deal: the offer expired.
1FDEALDECL1NED000The declined deal: credit declined.
Ava GoodSuper-prime persona (score 843): the payer cast's anchor.
F3TC22The estate's lender of record (the payoff registry's own counterparty).

1 — The search matches

capabilitysearch.providePOST /searches/provide

The journey opens where the world does: the saved search's own status door (world-keyed, vin-vje.38). The fresh-quote exemplar carries SearchFSM Matched — the match that started this deal.

runnable — sandbox · deterministic1FDEALFRESH000000
run it — POST /searches/provide
curl -X POST 'https://apis.vin/searches/provide' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALFRESH000000"}'
the world answers — SavedSearch@1
{
  "search": "srch_962ce7eb",
  "vin": "1FDEALFRESH000000",
  "status": "Matched",
  "matched": true
}

2 — The offer, on the desk's machine

capabilityoffer.makeoffer.acceptPOST /offers/make

The car desk adjudicates the OfferFSM: the fresh quote's offer already stands (already-extended, one OFR- identity), the acceptance accepts it at the desk's asking, an accepted offer answers already-accepted, and the expired one refuses offer-not-open. A fleet row without the deal arc answers no-deal-on-file — the desk never invents a fleet deal.

runnable — sandbox · deterministic1FDEALFRESH000000
run it — POST /offers/make
curl -X POST 'https://apis.vin/offers/make' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALFRESH000000"}'
the world answers — OfferMake@1
{
  "vin": "1FDEALFRESH000000",
  "noun": "offer",
  "asOf": "2026-08-10",
  "offer": { "status": "already-extended", "id": "OFR-63551724", "position": "Extended" }
}
runnable — sandbox · deterministic1FDEALFRESH000000
run it — POST /offers/accept
curl -X POST 'https://apis.vin/offers/accept' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALFRESH000000"}'
the world answers — OfferAccept@1
{
  "vin": "1FDEALFRESH000000",
  "noun": "offer",
  "asOf": "2026-08-10",
  "acceptance": { "status": "accepted", "id": "OFR-63551724", "amountCents": 2300000, "currency": "USD" }
}

3 — Apply for credit

capabilitycredit.applyPOST /credits/apply

The application door stays the generated fallback by RULED pin (vin-fvh5): a bureau pull without FCRA consent evidence answers a typed block — the consent gate stands in front of the pull, by design.

runnable — sandbox · deterministic1FDEALDESKED00000
run it — POST /credits/apply
curl -X POST 'https://apis.vin/credits/apply' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALDESKED00000","firstName":"Ava","lastName":"Good","zip":"94103"}'
the world answers — the consent gate
{
  "type": "BLOCKED",
  "reason": "FCRA consent evidence is required before a bureau pull"
}

4 — Attach the F&I menu

capabilityfni.selectPOST /fnis/select

The journey's own door (the uncontested pair's first half): the ONE documented menu — a flat VSC and a flat GAP — priced byte-for-byte under the payer cast, with the deal's standing on the wire. (The menu's divergence from the risk-money VSC-PLAT plan is a filed model-gap, attested below.)

runnable — sandbox · deterministic1FDEALDESKED00000
run it — POST /fnis/select
curl -X POST 'https://apis.vin/fnis/select' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALDESKED00000","products":["vsc","gap"],"firstName":"Ava","lastName":"Good","zip":"94103"}'
the world answers — FniSelection@1
{
  "vin": "1FDEALDESKED00000",
  "selectionId": "fni_2e829886",
  "buyer": { "name": "Ava Good", "castRow": "super-prime", "creditTier": "super-prime" },
  "products": [
    { "product": "vsc", "label": "Vehicle service contract", "termMonths": 60, "price": { "currency": "USD", "minorUnits": 249500 } },
    { "product": "gap", "label": "GAP waiver", "termMonths": 60, "price": { "currency": "USD", "minorUnits": 89500 } }
  ],
  "total": { "currency": "USD", "minorUnits": 339000 },
  "status": "Selected",
  "dealStatus": "DESKED"
}

5 — The out-the-door figure

capabilityotd.computeGET /otds/compute

The pair's second half — ONE derivation, every line owned elsewhere: the valuation book's OWN retail-average price at the world's one mileage (the same number valuation.retail answers), the title rail's OWN itemized fee estimate at that price (byte parity with title.fee), the selected menu products, minus the flat refundable deposit. Branded iron refuses the retail derivation outright (not-retailable — the disposition law).

runnable — sandbox · deterministic1FDEALDESKED00000
run it — GET /otds/compute
curl 'https://apis.vin/otds/compute?vin=1FDEALDESKED00000&state=AZ&products=vsc'
the world answers — OtdCompute@1
{
  "vin": "1FDEALDESKED00000",
  "state": "AZ",
  "priceBasis": "retail-average",
  "vehiclePrice": { "currency": "USD", "minorUnits": 4529355 },
  "feeLines": [
    { "code": "title-fee", "label": "Title fee", "amount": { "currency": "USD", "minorUnits": 1500 } },
    { "code": "registration-fee", "label": "Registration fee", "amount": { "currency": "USD", "minorUnits": 6500 } },
    { "code": "plate-fee", "label": "Plate/transfer fee", "amount": { "currency": "USD", "minorUnits": 2500 } },
    { "code": "doc-fee", "label": "Filing/doc fee", "amount": { "currency": "USD", "minorUnits": 8500 } },
    { "code": "tax-overlay", "label": "Title/registration tax", "amount": { "currency": "USD", "minorUnits": 271761 } }
  ],
  "feesAndTax": { "currency": "USD", "minorUnits": 290761 },
  "fiProducts": [
    { "product": "vsc", "label": "Vehicle service contract", "price": { "currency": "USD", "minorUnits": 249500 } }
  ],
  "fiTotal": { "currency": "USD", "minorUnits": 249500 },
  "outTheDoor": { "currency": "USD", "minorUnits": 5069616 },
  "deposit": { "currency": "USD", "minorUnits": 50000 },
  "amountFinanced": { "currency": "USD", "minorUnits": 5019616 },
  "dealStatus": "DESKED"
}

6 — Paper and sign

capabilityeContract.prepareesignature.capturePOST /e-contracts/prepare

The funding pipeline carries the paper under the desk's OWN DL- deal identity (one deal, both clusters), and the signing desk adjudicates the packet: the desked draft is packet-not-routed, the contracted exemplar answers already-captured under its SGN- ceremony, and a quote with no paper answers no-packet-on-file.

runnable — sandbox · deterministic1FDEALDESKED00000
run it — POST /e-contracts/prepare
curl -X POST 'https://apis.vin/e-contracts/prepare' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALDESKED00000"}'
the world answers — EContractPrepare@1
{
  "vin": "1FDEALDESKED00000",
  "noun": "eContract",
  "asOf": "2026-08-10",
  "id": "EC-8734d4f5",
  "dealId": "DL-6b4900ac",
  "documents": ["DOC-a6d18b01"],
  "status": "Generated",
  "preparation": { "status": "already-on-file", "id": "DOC-a6d18b01", "position": "Draft" }
}
runnable — sandbox · deterministic1FDEALS1GNED00000
run it — POST /esignatures/capture
curl -X POST 'https://apis.vin/esignatures/capture' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALS1GNED00000"}'
the world answers — EsignatureCapture@1
{
  "vin": "1FDEALS1GNED00000",
  "noun": "esignature",
  "asOf": "2026-08-10",
  "capture": { "status": "already-captured", "ceremonyId": "SGN-773653ed", "position": "Signed" }
}

7 — Money moves: payments and escrow

capabilityescrow.opendeal.fundPOST /escrows/open

The money movement itself stays with the commerce rail's door-owned wires — this journey never re-seeds them. The contracted exemplar's escrow opens held and its funding settles to the ledger:

runnable — sandbox · deterministic1FDEALS1GNED00000
run it — POST /escrows/open
curl -X POST 'https://apis.vin/escrows/open' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALS1GNED00000"}'
the world answers — EscrowOpen@1
{
  "escrow": {
    "$id": "escrow_es_1",
    "contractRef": "outcomecontract_1FDEALS1GNED00000",
    "amount": { "amount": "500000", "currency": "USD" },
    "state": "held"
  }
}

Honesty note: these commerce-rail answers are typed and deterministic but seeded, not world-derived — the escrow amount above is the rail's own figure, not this deal's out-the-door money, and the exemplar's curated PaymentFSM/EscrowFSM positions are not read by these doors. That gap is metered on the world-coherence ratchet, not papered over here.

8 — Title, registration, lien

capabilitytempTag.issuelien.recordPOST /temp-tags/issue

The tag desk adjudicates delivery and title: an undelivered deal refuses vehicle-not-delivered, the delivered exemplar's tag stands tag-already-issued with its expiry, and a transferred title answers permanent-plate-on-file — no tag needed.

runnable — sandbox · deterministic1FDEALDEL1VERED00
run it — POST /temp-tags/issue
curl -X POST 'https://apis.vin/temp-tags/issue' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALDEL1VERED00"}'
the world answers — TempTagIssue@1
{
  "vin": "1FDEALDEL1VERED00",
  "noun": "tempTag",
  "asOf": "2026-08-10",
  "plate": "TAG-f0e9254b",
  "state": "AZ",
  "issue": { "status": "tag-already-issued", "tagNumber": "TAG-f0e9254b", "expiresOn": "2026-09-09" }
}

Name the estate's lender of record and the lien records in its favor — the SAME F3TC22 counterparty payoff.quote answers for this fleet (the door's defaulting and standing gaps are filed, attested below):

runnable — sandbox · deterministic1FDEALFUNDED00000
run it — POST /liens/record
curl -X POST 'https://apis.vin/liens/record' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALFUNDED00000","financeSourceId":"F3TC22"}'
the world answers — LienRecord@1
{
  "vin": "1FDEALFUNDED00000",
  "noun": "lien",
  "asOf": "2026-08-10",
  "recording": {
    "status": "recorded",
    "id": "LIEN-7144b0d0",
    "lienholder": { "fsId": "F3TC22", "name": "Huntington National Bank" }
  }
}

9 — Transport

capabilitytransport.bookPOST /transports/book

The move rides the world-keyed logistics doors (wave 7): the in-fulfillment exemplar's carrier is already mid-route, and the booking answers that phase.

runnable — sandbox · deterministic1FDEALENR0UTE0000
run it — POST /transports/book
curl -X POST 'https://apis.vin/transports/book' \
  -H 'content-type: application/json' \
  -d '{"vin":"1FDEALENR0UTE0000"}'
the world answers — TransportOrder@1
{
  "vin": "1FDEALENR0UTE0000",
  "phase": "InTransit",
  "move": { "id": "TR-f2aa970b", "action": "book", "status": "booked", "rateCents": 89500, "currency": "USD" }
}

10 — Delivered

capabilitydeal.statusGET /deals/status

The desk's arc read closes the journey: the deal's DealLifecycle position under its one DL- identity.

runnable — sandbox · deterministic1FDEALDEL1VERED00
run it — GET /deals/status
curl 'https://apis.vin/deals/status?vin=1FDEALDEL1VERED00'
the world answers — DealStatus@1
{
  "vin": "1FDEALDEL1VERED00",
  "noun": "deal",
  "asOf": "2026-08-10",
  "deal": { "id": "DL-e7d149f4", "position": "DELIVERED", "orderId": "ORD-76ec4a4a", "askingCents": 2300000, "currency": "USD" }
}

Where the journey's ground is thin

Attested, not persuaded — each filed as a bd model-gap per the honest-grade law, with the journey suite pinning today's bytes as the tripwire:

  • The desk never adjudicates the retail laws — branded iron gets a retail offer, the declined exemplar gets a contract draft, the desk's flat asking is not the valuation book's band, and non-fleet VINs get seeded deals (vin-285f).
  • lien.record ignores loan standing and the lender registry — it records for an unfunded quote, defaults to a lienholder that is not the estate's lender of record, and "records" unsupported lenders (vin-75se).
  • Two F&I price stories — this journey's menu and risk-money's VSC-PLAT plan price the same product family differently (vin-5b2r).
  • The commerce rail's money — step 7's escrow and funding figures are the rail's own seeds, not this deal's out-the-door money.
  • The arc is curated positions, not witnessed transitions — no DealLifecycle edge is driven by these verbs' own events.

Next

  • Refinance — the note this journey books, refinanced.
  • Repossession — the deal arc run in reverse when the note defaults.
  • Sandbox test triggers — the full deterministic trigger register, including the persona cast this journey prices with.