InventoryLocations
Docs
    Dealer Brand App

    Decentralized Self-building Future

    Sign In
    Inventory
    Locations
    Service
    My Garage
    How I shop
    Privacy|Contact
    v1.106.1|Sonoratek LLC

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Dealer desk docs
    Getting started
    First day on the desk
    Features
    Vehicle inventory
    Vehicle stock
    Listing a vehicle by hand
    Rooftops and the dealer group
    Dealer leads
    Rooftop messages
    Garage and how you shop
    Push Notifications with FCM (Ring-Powered)
    Tunnel Protocol

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Dealer desk docs
    Getting started
    First day on the desk
    Features
    Vehicle inventory
    Vehicle stock
    Listing a vehicle by hand
    Rooftops and the dealer group
    Dealer leads
    Rooftop messages
    Garage and how you shop
    Push Notifications with FCM (Ring-Powered)
    Tunnel Protocol

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Dealer desk docs
    Getting started
    First day on the desk
    Features
    Vehicle inventory
    Vehicle stock
    Listing a vehicle by hand
    Rooftops and the dealer group
    Dealer leads
    Rooftop messages
    Garage and how you shop
    Push Notifications with FCM (Ring-Powered)
    Tunnel Protocol
    Dealer Brand App Logo

    Loading documentation...

    Preparing Dealer Brand App content

    Dealer Brand App Logo

    Loading documentation...

    Preparing Dealer Brand App content

    Dealer Brand App Logo

    Loading documentation...

    Preparing Dealer Brand App content

    Dealer leads

    On this pack an opportunity is a lead to a rooftop or to the dealer group. The shopper and that team's members share one messenger thread. The public browse feed is not how a store works a test drive.

    This page is the dealer-pack overlay of the opportunities article. Matcher, auto-fill, and the generic offer/request types still exist on Layer 1. The types below are the ones this pack adds and the clone enables.

    Shipped

    Creating a lead stores metadata.conversationId and the shopper is sent to /messages?c=. Chat about the same vehicle reuses the open inquiry. The product agent is not that thread.

    Lead kinds

    KindWho starts itDesk meaning
    vehicle_inquiryChat with seller, or check availabilityOne open thread per shopper and vehicle
    test_driveCard dialog or vehicle pageDate and time of day
    trade_inVehicle page or sell/tradeVIN and miles, optional asking price
    finance_inquiryAsk about financingA question. No SSN, no credit pull
    service_appointment/serviceRooftop, date, and a note
    product_offerSeller offer, other productsTitle, category, optional SKU and price
    partner_applicationHow I shop, dealer or supplierOne open application per person. Not a staff role

    Enabled on the DealerDirect clone in ring-config.json → opportunities.enabledTypes, together with offer, request, and job.

    Stages on the desk: new, contacted, appointment_set, showed, sold, lost.

    How a day on the desk works

    A shopper taps Chat, Test drive, Value my trade, Ask about financing, Book service, or sends an offer. They must be signed in. They land in Messages with your team already on the thread. You work the row at /dealer/leads.

    Sold and lost inquiries do not reopen. A new chat after that starts a new lead. A second chat while the inquiry is still open returns the same thread.

    Vehicle

    The buttons live on the inventory card and the vehicle page.

    Who is notified

    Members of that rooftop, and members of the parent group, can see the lead.

    Do not treat Ask about financing as a pre-approval. The copy tells the shopper there is no credit pull and no SSN. Do not add those fields.

    Create path

    POST /api/dealer/leads reads the session and calls createDealerLead in features/dealer/services/leads.ts.

    The opportunity is visibility: 'entity', organizationId is the rooftop or the group, and metadata holds leadKind, productId, vin, stockNumber, stage: 'new', and the form extras. openEntityLeadConversation uses conversation type opportunity, participant ids = shopper + getEntityTeamUserIds, and notifies the team with actionUrl: '/dealer/leads'.

    rememberConversation merges conversationId into existing metadata. The database update is a shallow JSON merge, so the helper reads the current metadata and spreads it. Passing only { conversationId } would wipe stage and the VIN.

    Reuse queries:

    • vehicle_inquiry where createdBy, metadata.productId match and stage is not sold or lost.
    • partner_application where createdBy matches and stage is not sold or lost.

    GET /api/dealer/leads returns rows the caller can see via loadViewerEntityAccessIds. Stage updates go through features/dealer/services/lead-pipeline.ts and require entity role MEMBER or a platform admin.

    Policy for every kind above lives in features/opportunities/lib/opportunity-type-policy.ts (minRole: subscriber, defaultVisibility: entity). partner_application is not on the four-tile add-opportunity picker (OPPORTUNITY_SELECTOR_TYPE_ORDER). It is created only from the audience API.

    A 200 body is { opportunityId, conversationId, rooftopId }. The client helper post-dealer-lead.ts routes to /messages?c=<conversationId>.

    Frequently asked questions

    Impact

    Is this the product agent?

    No. The agent uses agentChat=1 and conversation type product. Dealer leads use type opportunity and the rooftop team.

    Can a guest send a lead?

    No. The API returns 401. The button sends them to login and back to the vehicle, service page, or sell page.

    Migration

    What happened to the generic opportunity article's matcher loop?

    It still runs inside Layer 1 createOpportunity for types that go through that service. This page documents the dealer kinds and the thread handoff. Do not quote matcher accuracy percentages.

    Ops

    Why would chat open a thread with only the shopper?

    The rooftop entity had no members in memberRoles. Add staff on the entity. The lead row still exists.

    Not in this release

    Related documentation

    Vehicle inventory

    Prerequisite: the vehicle the lead is about.

    Rooftops and the dealer group

    Depends on: the rooftop or group the lead is addressed to.

    1. Docs
    2. /Features
    3. /Dealer leads

    Updated Oct 28, 20264 min listen

    Dealer leads

    On this pack an opportunity is a lead to a rooftop or to the dealer group. The shopper and that team's members share one messenger thread. The public browse feed is not how a store works a test drive.

    This page is the dealer-pack overlay of the opportunities article. Matcher, auto-fill, and the generic offer/request types still exist on Layer 1. The types below are the ones this pack adds and the clone enables.

    Shipped

    Creating a lead stores metadata.conversationId and the shopper is sent to /messages?c=. Chat about the same vehicle reuses the open inquiry. The product agent is not that thread.

    Lead kinds

    KindWho starts itDesk meaning
    vehicle_inquiryChat with seller, or check availabilityOne open thread per shopper and vehicle
    test_driveCard dialog or vehicle pageDate and time of day
    trade_inVehicle page or sell/tradeVIN and miles, optional asking price
    finance_inquiryAsk about financingA question. No SSN, no credit pull
    service_appointment/serviceRooftop, date, and a note
    product_offerSeller offer, other productsTitle, category, optional SKU and price
    partner_applicationHow I shop, dealer or supplierOne open application per person. Not a staff role

    Enabled on the DealerDirect clone in ring-config.json → opportunities.enabledTypes, together with offer, request, and job.

    Stages on the desk: new, contacted, appointment_set, showed, sold, lost.

    How a day on the desk works

    A shopper taps Chat, Test drive, Value my trade, Ask about financing, Book service, or sends an offer. They must be signed in. They land in Messages with your team already on the thread. You work the row at /dealer/leads.

    Sold and lost inquiries do not reopen. A new chat after that starts a new lead. A second chat while the inquiry is still open returns the same thread.

    Vehicle

    The buttons live on the inventory card and the vehicle page.

    Who is notified

    Members of that rooftop, and members of the parent group, can see the lead.

    Do not treat Ask about financing as a pre-approval. The copy tells the shopper there is no credit pull and no SSN. Do not add those fields.

    Create path

    POST /api/dealer/leads reads the session and calls createDealerLead in features/dealer/services/leads.ts.

    The opportunity is visibility: 'entity', organizationId is the rooftop or the group, and metadata holds leadKind, productId, vin, stockNumber, stage: 'new', and the form extras. openEntityLeadConversation uses conversation type opportunity, participant ids = shopper + getEntityTeamUserIds, and notifies the team with actionUrl: '/dealer/leads'.

    rememberConversation merges conversationId into existing metadata. The database update is a shallow JSON merge, so the helper reads the current metadata and spreads it. Passing only { conversationId } would wipe stage and the VIN.

    Reuse queries:

    • vehicle_inquiry where createdBy, metadata.productId match and stage is not sold or lost.
    • partner_application where createdBy matches and stage is not sold or lost.

    GET /api/dealer/leads returns rows the caller can see via loadViewerEntityAccessIds. Stage updates go through features/dealer/services/lead-pipeline.ts and require entity role MEMBER or a platform admin.

    Policy for every kind above lives in features/opportunities/lib/opportunity-type-policy.ts (minRole: subscriber, defaultVisibility: entity). partner_application is not on the four-tile add-opportunity picker (OPPORTUNITY_SELECTOR_TYPE_ORDER). It is created only from the audience API.

    A 200 body is { opportunityId, conversationId, rooftopId }. The client helper post-dealer-lead.ts routes to /messages?c=<conversationId>.

    Frequently asked questions

    Impact

    Is this the product agent?

    No. The agent uses agentChat=1 and conversation type product. Dealer leads use type opportunity and the rooftop team.

    Can a guest send a lead?

    No. The API returns 401. The button sends them to login and back to the vehicle, service page, or sell page.

    Migration

    What happened to the generic opportunity article's matcher loop?

    It still runs inside Layer 1 createOpportunity for types that go through that service. This page documents the dealer kinds and the thread handoff. Do not quote matcher accuracy percentages.

    Ops

    Why would chat open a thread with only the shopper?

    The rooftop entity had no members in memberRoles. Add staff on the entity. The lead row still exists.

    Not in this release

    Related documentation

    Vehicle inventory

    Prerequisite: the vehicle the lead is about.

    Rooftops and the dealer group

    Depends on: the rooftop or group the lead is addressed to.

    1. Docs
    2. /Features
    3. /Dealer leads

    Updated Oct 28, 20264 min listen

    Dealer leads

    On this pack an opportunity is a lead to a rooftop or to the dealer group. The shopper and that team's members share one messenger thread. The public browse feed is not how a store works a test drive.

    This page is the dealer-pack overlay of the opportunities article. Matcher, auto-fill, and the generic offer/request types still exist on Layer 1. The types below are the ones this pack adds and the clone enables.

    Shipped

    Creating a lead stores metadata.conversationId and the shopper is sent to /messages?c=. Chat about the same vehicle reuses the open inquiry. The product agent is not that thread.

    Lead kinds

    KindWho starts itDesk meaning
    vehicle_inquiryChat with seller, or check availabilityOne open thread per shopper and vehicle
    test_driveCard dialog or vehicle pageDate and time of day
    trade_inVehicle page or sell/tradeVIN and miles, optional asking price
    finance_inquiryAsk about financingA question. No SSN, no credit pull
    service_appointment/serviceRooftop, date, and a note
    product_offerSeller offer, other productsTitle, category, optional SKU and price
    partner_applicationHow I shop, dealer or supplierOne open application per person. Not a staff role

    Enabled on the DealerDirect clone in ring-config.json → opportunities.enabledTypes, together with offer, request, and job.

    Stages on the desk: new, contacted, appointment_set, showed, sold, lost.

    How a day on the desk works

    A shopper taps Chat, Test drive, Value my trade, Ask about financing, Book service, or sends an offer. They must be signed in. They land in Messages with your team already on the thread. You work the row at /dealer/leads.

    Sold and lost inquiries do not reopen. A new chat after that starts a new lead. A second chat while the inquiry is still open returns the same thread.

    Vehicle

    The buttons live on the inventory card and the vehicle page.

    Who is notified

    Members of that rooftop, and members of the parent group, can see the lead.

    Do not treat Ask about financing as a pre-approval. The copy tells the shopper there is no credit pull and no SSN. Do not add those fields.

    Create path

    POST /api/dealer/leads reads the session and calls createDealerLead in features/dealer/services/leads.ts.

    The opportunity is visibility: 'entity', organizationId is the rooftop or the group, and metadata holds leadKind, productId, vin, stockNumber, stage: 'new', and the form extras. openEntityLeadConversation uses conversation type opportunity, participant ids = shopper + getEntityTeamUserIds, and notifies the team with actionUrl: '/dealer/leads'.

    rememberConversation merges conversationId into existing metadata. The database update is a shallow JSON merge, so the helper reads the current metadata and spreads it. Passing only { conversationId } would wipe stage and the VIN.

    Reuse queries:

    • vehicle_inquiry where createdBy, metadata.productId match and stage is not sold or lost.
    • partner_application where createdBy matches and stage is not sold or lost.

    GET /api/dealer/leads returns rows the caller can see via loadViewerEntityAccessIds. Stage updates go through features/dealer/services/lead-pipeline.ts and require entity role MEMBER or a platform admin.

    Policy for every kind above lives in features/opportunities/lib/opportunity-type-policy.ts (minRole: subscriber, defaultVisibility: entity). partner_application is not on the four-tile add-opportunity picker (OPPORTUNITY_SELECTOR_TYPE_ORDER). It is created only from the audience API.

    A 200 body is { opportunityId, conversationId, rooftopId }. The client helper post-dealer-lead.ts routes to /messages?c=<conversationId>.

    Frequently asked questions

    Impact

    Is this the product agent?

    No. The agent uses agentChat=1 and conversation type product. Dealer leads use type opportunity and the rooftop team.

    Can a guest send a lead?

    No. The API returns 401. The button sends them to login and back to the vehicle, service page, or sell page.

    Migration

    What happened to the generic opportunity article's matcher loop?

    It still runs inside Layer 1 createOpportunity for types that go through that service. This page documents the dealer kinds and the thread handoff. Do not quote matcher accuracy percentages.

    Ops

    Why would chat open a thread with only the shopper?

    The rooftop entity had no members in memberRoles. Add staff on the entity. The lead row still exists.

    Not in this release

    Related documentation

    Vehicle inventory

    Prerequisite: the vehicle the lead is about.

    Rooftops and the dealer group

    Depends on: the rooftop or group the lead is addressed to.

    1. Docs
    2. /Features
    3. /Dealer leads

    Updated Oct 28, 20264 min listen