campaign
The campaign noun — identity, lifecycle, events, and every capability as an anchored section: 27 capabilities, 0 live, 27 sandbox, 0 declared.
campaign is one of the estate's 317 automotive nouns — a job a car needs done. It carries 27 capabilities: 0 live, 27 sandbox, 0 declared · doors aggregator.vin.
Identity
| Noun | campaign |
| Pillar | Data (facets: 12 data · 10 services · 5 commerce) |
| Capabilities | 27 — 0 live · 27 sandbox · 0 declared |
| Entities | MarketingCampaign |
| Doors | aggregator.vin |
| SDK | Vin.campaign.* from apis.vin |
| Address | /catalog/campaign#{action} — the anchor IS the wire name minus campaign. |
Lifecycle
MarketingCampaign — CampaignLifecycleFSM: 5 states, 6 transitions — Draft · Scheduled · Live · Paused · Completed. Each transition is a past-tense event on the record.
Events
The vocabulary this noun can append to the record — 26 past-tense, versioned event types, each linked to the capability that emits it:
Campaign.budgeted@1— emitted bybudgetCampaign.claimFailed@1— emitted byclaimCampaign.claimRequested@1— emitted byclaimCampaign.claimed@1— emitted byclaimCampaign.completeRequested@1— emitted bycompleteCampaign.completed@1— emitted bystatusCampaign.created@1— emitted bycreateCampaign.equityMined@1— emitted byequityMineCampaign.failed@1— emitted bybudget·payCampaign.launched@1— emitted bylaunchCampaign.notified@1— emitted bynotifyCampaign.notifyRequested@1— emitted bynotifyCampaign.optimized@1— emitted byoptimizeCampaign.paid@1— emitted bypayCampaign.paused@1— emitted bypauseCampaign.performFailed@1— emitted byperformCampaign.performRequested@1— emitted byperformCampaign.performed@1— emitted byperformCampaign.scheduleRequested@1— emitted byscheduleCampaign.scheduled@1— emitted byscheduleCampaign.settleFailed@1— emitted bysettleCampaign.settleRequested@1— emitted bysettleCampaign.settled@1— emitted bysettleCampaign.targeted@1— emitted bytargetCampaign.warrantyBillRequested@1— emitted bywarrantyBillCampaign.warrantyBilled@1— emitted bywarrantyBill
Discover & read
lookup
campaign.lookup · GET /campaigns/lookup · gate none · sandbox · answers CampaignLookup@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.lookup({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/lookup?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignLookup@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}read
campaign.read · GET /campaigns/read · gate none · sandbox · answers CampaignRead@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.read({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/read?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignRead@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}status
campaign.status · GET /campaigns/status · gate none · sandbox · answers CampaignStatus@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
asOf | string | no | format date-time; observation instant (≡ the x-world-as-of header); the answer states the campaign lifecycle AT this instant — absent, at, or before the fixed as-of answers the unmoved world (the campaign-flight-end monitor closes a Live flight Completed past its dueAt) |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.completed@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.status({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/status?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignStatus@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}remedyLookup
campaign.remedyLookup · GET /campaigns/remedy-lookup · gate none · sandbox · answers CampaignRemedyLookup@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.remedyLookup({"vin":"1FTFW1RGXSFA22229"})curl 'https://apis.vin/campaigns/remedy-lookup?vin=1FTFW1RGXSFA22229'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignRemedyLookup@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"remedyAvailable": false
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"remedyAvailable": false
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}statusRead
campaign.statusRead · GET /campaigns/status-read · gate none · sandbox · answers CampaignStatusRead@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.statusRead({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/status-read?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignStatusRead@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"status": "scheduled"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}budget
campaign.budget · POST /campaigns/budget · gate offer · sandbox · answers CampaignBudget@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.budgeted@1 · Campaign.failed@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.budget({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/budget \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignBudget@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"budgetCents": 500000,
"currency": "USD"
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"budgetCents": 500000,
"currency": "USD"
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}target
campaign.target · POST /campaigns/target · gate offer · sandbox · answers CampaignTarget@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.targeted@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.target({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/target \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignTarget@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "target",
"status": "scheduled"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "target",
"status": "scheduled"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}eligibilityCheck
campaign.eligibilityCheck · GET /campaigns/eligibility-check · gate none · sandbox · answers CampaignEligibilityCheck@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.eligibilityCheck({"vin":"1FTFW1RGXSFA22229"})curl 'https://apis.vin/campaigns/eligibility-check?vin=1FTFW1RGXSFA22229'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignEligibilityCheck@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"eligible": false
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"eligible": false
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}Apply & book
schedule
campaign.schedule · POST /campaigns/schedule · gate offer · sandbox · answers CampaignSchedule@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.scheduleRequested@1 · Campaign.scheduled@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.schedule({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/schedule \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignSchedule@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "schedule",
"status": "scheduled"
},
"refusal": {
"code": "ILLEGAL_TRANSITION",
"from": "scheduled",
"on": "Campaign.scheduled@1",
"legalFrom": [
"draft"
]
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "schedule",
"status": "scheduled"
},
"refusal": {
"code": "ILLEGAL_TRANSITION",
"from": "scheduled",
"on": "Campaign.scheduled@1",
"legalFrom": [
"draft"
]
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}create
campaign.create · POST /campaigns/create · gate offer · sandbox · answers CampaignCreate@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.created@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.create({"vin":"1FTFW1RGXSFA22229"})curl -X POST https://apis.vin/campaigns/create \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignCreate@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "CAMP-1ba9593d",
"type": "marketing",
"action": "create",
"status": "draft"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "CAMP-1ba9593d",
"type": "marketing",
"action": "create",
"status": "draft"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}Pay & settle
pay
campaign.pay · POST /campaigns/pay · gate offer · sandbox · answers CampaignPay@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.failed@1 · Campaign.paid@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.pay({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/pay \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignPay@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"payment": {
"id": "PAY-5a5fcdf2",
"status": "settled",
"amountCents": 38000,
"currency": "USD"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"payment": {
"id": "PAY-5a5fcdf2",
"status": "settled",
"amountCents": 38000,
"currency": "USD"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}settle
campaign.settle · POST /campaigns/settle · gate offer · sandbox · answers CampaignSettle@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.settleFailed@1 · Campaign.settleRequested@1 · Campaign.settled@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.settle({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/settle \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignSettle@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"payment": {
"id": "PAY-ce56d773",
"status": "settled",
"amountCents": 38000,
"currency": "USD"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"payment": {
"id": "PAY-ce56d773",
"status": "settled",
"amountCents": 38000,
"currency": "USD"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}warrantyBill
campaign.warrantyBill · POST /campaigns/warranty-bill · gate offer · sandbox · answers CampaignWarrantyBill@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.warrantyBillRequested@1 · Campaign.warrantyBilled@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.warrantyBill({"vin":"1FTFW1RGXSFA22229"})curl -X POST https://apis.vin/campaigns/warranty-bill \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignWarrantyBill@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "CAMP-1ba9593d",
"bill": {
"id": "CB-c23281ac",
"billable": false,
"amountCents": 0,
"currency": "USD",
"status": "nothing-to-bill"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "CAMP-1ba9593d",
"bill": {
"id": "CB-c23281ac",
"billable": false,
"amountCents": 0,
"currency": "USD",
"status": "nothing-to-bill"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}Fulfill & operate
perform
campaign.perform · POST /campaigns/perform · gate offer · sandbox · answers CampaignPerform@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.performFailed@1 · Campaign.performRequested@1 · Campaign.performed@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.perform({"vin":"1FTFW1RGXSFA22229"})curl -X POST https://apis.vin/campaigns/perform \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignPerform@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "CAMP-1ba9593d",
"work": {
"id": "CW-bf6f978d",
"operation": "perform",
"status": "no-open-campaign"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "CAMP-1ba9593d",
"work": {
"id": "CW-bf6f978d",
"operation": "perform",
"status": "no-open-campaign"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}complete
campaign.complete · POST /campaigns/complete · gate offer · sandbox · answers CampaignComplete@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.completeRequested@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.complete({"vin":"1FTFW1RGXSFA22229"})curl -X POST https://apis.vin/campaigns/complete \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignComplete@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "CAMP-1ba9593d",
"work": {
"id": "CW-a7646bd7",
"operation": "complete",
"status": "no-open-campaign"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "CAMP-1ba9593d",
"work": {
"id": "CW-a7646bd7",
"operation": "complete",
"status": "no-open-campaign"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}notify
campaign.notify · POST /campaigns/notify · gate offer · sandbox · answers CampaignNotify@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.notified@1 · Campaign.notifyRequested@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.notify({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/notify \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignNotify@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "notify",
"status": "scheduled"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "notify",
"status": "scheduled"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}Authorize & resolve
claim
campaign.claim · POST /campaigns/claim · gate offer · sandbox · answers CampaignClaim@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.claimFailed@1 · Campaign.claimRequested@1 · Campaign.claimed@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.claim({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/claim \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignClaim@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"payment": {
"id": "PAY-472005e0",
"status": "settled",
"amountCents": 38000,
"currency": "USD"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"payment": {
"id": "PAY-472005e0",
"status": "settled",
"amountCents": 38000,
"currency": "USD"
},
"payer": {
"name": "Ava Good",
"castRow": "super-prime",
"creditTier": "super-prime"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}More actions
attribution
campaign.attribution · GET /campaigns/attribution · gate key · sandbox · answers CampaignAttribution@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.attribution({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/attribution?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignAttribution@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"impressions": 38459,
"conversions": 19
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"impressions": 38459,
"conversions": 19
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}audience
campaign.audience · GET /campaigns/audience · gate key · sandbox · answers CampaignAudience@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.audience({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/audience?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignAudience@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"audienceSize": 3426
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"audienceSize": 3426
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}byVin
campaign.byVin · GET /campaigns/by-vin · gate none · sandbox · answers CampaignByVin@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.byVin({"vin":"1FTFW1RGXSFA22229"})curl 'https://apis.vin/campaigns/by-vin?vin=1FTFW1RGXSFA22229'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignByVin@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaigns": [],
"openCount": 0
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaigns": [],
"openCount": 0
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}equityMine
campaign.equityMine · POST /campaigns/equity-mine · gate key · sandbox · answers CampaignEquityMine@1
| Field | Type | Required | Notes |
|---|---|---|---|
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.equityMined@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.equityMine({"campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/equity-mine \
-H 'content-type: application/json' \
-d '{"campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignEquityMine@1",
"value": {
"vin": "1HGCM82633A004352",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"candidates": 340,
"criterion": "positive-equity"
},
"evidence": {
"vin": "1HGCM82633A004352",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"candidates": 340,
"criterion": "positive-equity"
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}launch
campaign.launch · POST /campaigns/launch · gate offer · sandbox · answers CampaignLaunch@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.launched@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.launch({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/launch \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignLaunch@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "launch",
"status": "live"
},
"transition": {
"from": "scheduled",
"to": "live",
"on": "Campaign.launched@1"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "launch",
"status": "live"
},
"transition": {
"from": "scheduled",
"to": "live",
"on": "Campaign.launched@1"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [
"Campaign.launched@1"
],
"meter": {
"charged": "0.00",
"posted": false
}
}optimize
campaign.optimize · POST /campaigns/optimize · gate offer · sandbox · answers CampaignOptimize@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.optimized@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.optimize({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/optimize \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignOptimize@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "optimize",
"status": "scheduled"
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "optimize",
"status": "scheduled"
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}pause
campaign.pause · POST /campaigns/pause · gate offer · sandbox · answers CampaignPause@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
The gate is a 402 OFFER — the price and a hard ceiling on the wire, with a durable intent that executes on settlement. Never a wall, never "contact sales". Price: not posted — see /pricing.
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
Emits — Campaign.paused@1.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.pause({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl -X POST https://apis.vin/campaigns/pause \
-H 'content-type: application/json' \
-d '{"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"}'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignPause@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "pause",
"status": "scheduled"
},
"refusal": {
"code": "ILLEGAL_TRANSITION",
"from": "scheduled",
"on": "Campaign.paused@1",
"legalFrom": [
"live"
]
}
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaign": {
"id": "campaignid",
"type": "marketing",
"action": "pause",
"status": "scheduled"
},
"refusal": {
"code": "ILLEGAL_TRANSITION",
"from": "scheduled",
"on": "Campaign.paused@1",
"legalFrom": [
"live"
]
}
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}performance
campaign.performance · GET /campaigns/performance · gate key · sandbox · answers CampaignPerformance@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.performance({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/performance?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignPerformance@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"impressions": 38459,
"conversions": 19
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"impressions": 38459,
"conversions": 19
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}roi
campaign.roi · GET /campaigns/roi · gate key · sandbox · answers CampaignRoi@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.roi({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/roi?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignRoi@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"roiPct": 122
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"roiPct": 122
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}spend
campaign.spend · GET /campaigns/spend · gate key · sandbox · answers CampaignSpend@1
| Field | Type | Required | Notes |
|---|---|---|---|
vin | string | no | — |
campaignId | string | no | the marketing campaign addressed (CAMP-…); omit to address the default campaign derived from the VIN owner |
Door — aggregator.vin serves this noun on its two routes: / (the landing) · /1FTFW1RGXSFA22229 (the VIN lens).
Try it — sandbox: every call answers a deterministic, provenance-labeled simulated payload ({ environment, simulated } in the body). Force any documented outcome with the magic triggers. Going live is a connect, never a ballot: submit the credential at integrates.vin (dealer systems) or connects.vin (consumer accounts) — submissions enter the activation queue and rank live rollout.
import { campaign } from 'apis.vin'
// the gate law is in the type system: Answer<T> = Ok | Empty | Blocked | Offer
const answer = await campaign.spend({"vin":"1FTFW1RGXSFA22229","campaignId":"campaignid"})curl 'https://apis.vin/campaigns/spend?vin=1FTFW1RGXSFA22229&campaignId=campaignid'Receipt — the sandbox wire answered the request above with this exact body at build time. Captured by the receipts runner (timestamped, provenance in the payload), never authored; it re-executes only when this descriptor changes.
{
"type": "OK",
"answers": "CampaignSpend@1",
"value": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"spendCents": 190369,
"currency": "USD"
},
"evidence": {
"vin": "1FTFW1RGXSFA22229",
"noun": "campaign",
"asOf": "2026-08-10",
"campaignId": "campaignid",
"spendCents": 190369,
"currency": "USD"
},
"provenance": {
"simulated": true,
"environment": "sandbox",
"source": "aftersales-data-sandbox"
},
"events": [],
"meter": {
"charged": "0.00",
"posted": false
}
}Data model
The record shape behind this noun — one entity, each property an evidence field. See the whole estate model on the data model page.
MarketingCampaign
Schema
| Property | Type |
|---|---|
id | id |
name | string |
channel | string |
dealerId | ref→Dealer |
leadId | ref→Lead |
budgetCents | money |
status | CampaignLifecycleFSM |
Relationships
| From | To | Cardinality | As |
|---|---|---|---|
campaign | lead | *:1 | nurtures |
campaign | dealer | *:1 | run-by |
Modeled
The noun drawn out — its record shape, its lifecycle, and how it is exercised end to end. 3 diagrams, rendered from the estate model.
Campaign · Class model
Campaign · State machine
Campaign · Sequence
Generated from the catalog. Every capability, answer, gate, and entity on this page is a rendered descriptor — it cannot drift from the wire.