Save rooftop details

Saves the rooftop profile, the admin's phone and the rooftop's vehicle types in one call.

POSThttps://api.spyne.ai/console/v1/product-onboarding/update-rooftop-data
AuthBearer token (console user)Rate limitNot documentedProcessingSynchronous. Waits for every write (30 s timeout each); writes are not rolled back.

This call fans out to several writes in parallel and waits for them:

  • Updates the rooftop record: name, website, address, coordinates, region, timezone and website listing URL. It also updates the admin user's ISD code and phone (rooftopData.userData).
  • Saves the rooftop configuration (domain: rooftop, entity: INFO) with vehicleType and any department addresses. Keys you leave out are kept.
  • When entity is one of sales_inbound, sales_outbound, service_inbound, service_outbound, it also saves the agent configuration for that entity with entityConfig. The rooftop UI sends entity: "INFO", so this write does not run from the UI.
  • When rooftopData.address is present, it syncs the address to the dealer website location record. A failure there is logged and ignored.

When all writes finish, it tries to update the checklist task named in taskName for productLineId. Errors from that step are logged and ignored. The response does not echo saved data.

Before you call it

  • You need enterpriseId, teamId and the rooftop name.

  • The rooftop record update rejects the request unless all of these are set:

    • rooftopData.website (a non-empty string; https:// is added if missing)
    • rooftopData.address with non-empty addressLine1, city, state, country and zipcode, plus addressLine2 and district as strings (can be empty)
    • rooftopData.geoCoordinates.lat and lng as numbers in range
    • rooftopData.timeZone
    • rooftopData.regionType
    • rooftopData.websiteListingUrl, which must be a valid URL when sent
  • Always send entityConfig, even if it only holds vehicleType. Leaving it out returns 500.

  • Authentication: Bearer token of a signed-in console user. The same token is forwarded to each write.

  • Rate limit: Not documented

  • Processing: Synchronous. Waits for every write (30 second timeout each). The writes are not a transaction: if one fails after another succeeded, the successful write is not rolled back.


Request

Requiredalways sendOptionalcan be left out
Request checklist
  1. Read the current values with Get rooftop details and Get vehicle types and department addresses.
  2. Build rooftopData with the full address and coordinates.
  3. Send entityConfig.vehicleType with new and preOwned.
  4. Send domain: "rooftop" and entity: "INFO", as the UI does.
  5. On 2xx, call Mark a checklist task done with {teamId, taskName: "RoofTop Setup", isCompleted: true}.
ParameterTypeRequiredDescription
Headers——Sent as HTTP headers.
AuthorizationstringRequiredBearer YOUR_TOKEN
Content-TypestringRequiredapplication/json
Body——Sent as a JSON body.
enterpriseIdstringRequiredDealer group ID.
teamIdstringRequiredRooftop ID.
teamNamestringRequiredRooftop name to save.
enterpriseNamestringOptionalDealer group name, stored on the configuration record.
rooftopDataobjectRequiredRooftop profile.
rooftopData.websitestringRequiredRooftop website. See Before you call it.
rooftopData.websiteListingUrlstringOptionalInventory listing page URL.
rooftopData.addressobjectRequiredaddressLine1, addressLine2, city, state, district, country, zipcode. See Before you call it.
rooftopData.geoCoordinatesobjectRequired{lat, lng} numbers. See Before you call it.
rooftopData.regionTypestringRequiredRegion code. See Before you call it.
rooftopData.timeZonestringRequiredIANA timezone, e.g. America/Chicago. See Before you call it.
rooftopData.userDataobjectOptional{userId, name, email, contactNo, isdCode}. Only isdCode and contactNo are saved, for userId.
entityConfigobjectRequiredLeaving it out returns 500.
entityConfig.vehicleTypeobjectOptional{new: boolean, preOwned: boolean}.
entityConfig.salesAddress / serviceAddress / partsAddress / financeAddressobjectOptional{address, geoCoordinates{lat, lng}}. The UI does not send these.
domainstringOptionalUsed only for the agent configuration write. The UI sends rooftop.
entitystringOptionalsales_inbound, sales_outbound, service_inbound or service_outbound also triggers the agent configuration write. The UI sends INFO.
productLineIdstringOptionalWith taskName, updates that checklist task. The UI does not send it.
taskNamestringOptionalChecklist task to update.
segmentNamestringOptionalAgent segment of the task. Needed for Vini product lines.
isCompletedbooleanOptionaltrue = complete the task, otherwise start it.

Sample request

curl -X POST "https://api.spyne.ai/console/v1/product-onboarding/update-rooftop-data" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enterpriseId": "<enterpriseId>",
    "enterpriseName": "Example Motors Group",
    "teamId": "<teamId>",
    "teamName": "Example Motors",
    "domain": "rooftop",
    "entity": "INFO",
    "rooftopData": {
      "website": "https://www.example.com",
      "websiteListingUrl": "https://www.example.com/used-inventory",
      "address": {
        "addressLine1": "100 Example Ave", "addressLine2": "", "city": "Austin",
        "state": "TX", "district": "", "country": "United States", "zipcode": "78701"
      },
      "geoCoordinates": { "lat": 30.2672, "lng": -97.7431 },
      "regionType": "AMER",
      "timeZone": "America/Chicago",
      "userData": { "userId": "<userId>", "name": "Jane Doe", "email": "[email protected]", "contactNo": "5550100000", "isdCode": "+1" }
    },
    "entityConfig": { "vehicleType": { "new": true, "preOwned": true } }
  }'
import requests

payload = {
    "enterpriseId": "<enterpriseId>",
    "enterpriseName": "Example Motors Group",
    "teamId": "<teamId>",
    "teamName": "Example Motors",
    "domain": "rooftop",
    "entity": "INFO",
    "rooftopData": {
        "website": "https://www.example.com",
        "websiteListingUrl": "https://www.example.com/used-inventory",
        "address": {"addressLine1": "100 Example Ave", "addressLine2": "", "city": "Austin",
                    "state": "TX", "district": "", "country": "United States", "zipcode": "78701"},
        "geoCoordinates": {"lat": 30.2672, "lng": -97.7431},
        "regionType": "AMER",
        "timeZone": "America/Chicago",
        "userData": {"userId": "<userId>", "name": "Jane Doe", "email": "[email protected]",
                     "contactNo": "5550100000", "isdCode": "+1"},
    },
    "entityConfig": {"vehicleType": {"new": True, "preOwned": True}},
}
res = requests.post(
    "https://api.spyne.ai/console/v1/product-onboarding/update-rooftop-data",
    json=payload,
    headers={"Authorization": "Bearer YOUR_TOKEN"},
)
print(res.status_code, res.json())
const res = await fetch("https://api.spyne.ai/console/v1/product-onboarding/update-rooftop-data", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_TOKEN", "Content-Type": "application/json" },
  body: JSON.stringify({
    enterpriseId: "<enterpriseId>",
    enterpriseName: "Example Motors Group",
    teamId: "<teamId>",
    teamName: "Example Motors",
    domain: "rooftop",
    entity: "INFO",
    rooftopData: {
      website: "https://www.example.com",
      websiteListingUrl: "https://www.example.com/used-inventory",
      address: { addressLine1: "100 Example Ave", addressLine2: "", city: "Austin", state: "TX", district: "", country: "United States", zipcode: "78701" },
      geoCoordinates: { lat: 30.2672, lng: -97.7431 },
      regionType: "AMER",
      timeZone: "America/Chicago",
      userData: { userId: "<userId>", name: "Jane Doe", email: "[email protected]", contactNo: "5550100000", isdCode: "+1" },
    },
    entityConfig: { vehicleType: { new: true, preOwned: true } },
  }),
});
console.log(res.status, await res.json());

Sample response

{ "success": true, "message": "Successfully updated rooftop data", "data": {}, "error": false }
{ "error": true, "message": "Missing required fields: enterpriseId, teamId, teamName, and rooftopData are required" }
{
  "message": "Address.zipcode: zipcode is required, Timezone: Timezone must be a non-empty string",
  "error": true,
  "details": { "message": "Address.zipcode: zipcode is required, Timezone: Timezone must be a non-empty string", "error": true, "code": "ERROR_BAD_REQ_400", "details": null, "data": null }
}
{ "message": "Invalid Token", "error": true, "code": "ERROR_AUTH_401", "details": "", "data": null }
{ "message": "connect ECONNREFUSED ...", "error": true, "code": "ERROR_REQ_TIMEOUT_408", "details": "", "data": null }
{ "message": "No response received from one or more APIs", "error": true, "details": null }
{ "message": "Error setting up API requests", "error": true, "details": null }

Response fields

ParameterTypeDescription
successbooleantrue on 200.
messagestringSuccessfully updated rooftop data.
dataobjectAlways {}.
errorbooleanfalse on 200.

Errors

StatusReasonWhen it happens
400Missing required fieldsenterpriseId, teamId, teamName or rooftopData is missing.
4xx / 5xxPassed throughA downstream write answered with an error status. message is the downstream message and details is the downstream body. For example, 400 for rooftop field validation (a missing rooftopData.website also returns 400 here), or 401 from the configuration write.
401ERROR_AUTH_401Missing or invalid bearer token.
408ERROR_REQ_TIMEOUT_408The token check could not reach the auth service.
502No response received from one or more APIsA downstream write timed out or did not answer.
500Error setting up API requestsThe request could not be built. This includes a missing entityConfig.

Checklist-task errors (unknown task, task not started yet) are not returned. The call still returns 200.

Next

After a 2xx, call Mark a checklist task done with {teamId: "<teamId>", taskName: "RoofTop Setup", isCompleted: true}. Task names are matched without regard to case. With no segmentName, the task is completed for every segment of the rooftop. The UI does this without waiting for the result. CNAM Registration later reads the saved address and website.


Did this page help you?