Create an inventory feed workflow
Create the workflow that receives the rooftop's inventory feed from a partner.
The server validates the body, looks up the dealer group's owner user and the rooftop's reseller status, and applies partner flags (CGI-only partners get the CGI flow; some partners get image ids in output links). It then saves the workflow and its rules and clears the feed cache for the rooftop. After the save it opens a partner onboarding request with the partner name and any contact fields sent. If any of productOptions.spin, catalog or featureVideo is true, it also starts an inventory pull from the partner in the background. Only one non-reseller workflow can exist per partnerId + dealerId.
Before you call it
- You need the bearer token of a signed-in console user. The route does not check that the rooftop belongs to the caller.
- Get
partnerIdfrom List inventory and history partners withcategory=IMS, and the rooftop's dealer id at that partner. - Check List inventory feed workflows first. If a workflow for the same
partnerId+dealerIdexists, update it instead. partnerIdanddealerIdare required. A partner that is not in the list cannot be saved through this endpoint.- The save is synchronous. The partner onboarding request and the inventory pull run in the background; their failures are not reported. Rate limit: not documented.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
| Header | — | — | — |
Authorization | string | Required | Bearer YOUR_TOKEN |
| Body | — | — | — |
name | string | Required | Workflow name. The UI sends <partner name> - Inventory Provider. |
partnerId | string | Required | Partner id from the partner list. Must be a valid id of an existing partner. |
dealerId | string | Required | The rooftop's id at the partner. |
teamId | string | Required | <teamId> of the rooftop. |
enterpriseId | string | Optional | <enterpriseId>. Optional in validation, but send it. When sent, the dealer group's owner user must be found or the request fails with 400. |
partnerProviderTypes | string[] | Optional | Any of IMS, PHOTO, CGI. Default empty. Send ["IMS"] for the inventory feed. |
isActive | boolean | Optional | Default true. |
createDraft | boolean | Optional | Default false. The UI sends true. |
thresholdCounts | object | Optional | newCars and usedCars, numbers. 0 is rejected; use -1 to disable. |
preliminaryConfigs | object | Optional | enabled (boolean) and thresholds with new and used (numbers). |
productOptions | object | Optional | spin, catalog, featureVideo (validated as booleans), mediaKit, conversationalAi. |
processingConfigs | object | Optional | backgroundId (number), numberplateId, bannerId, videoId, voiceId, musicId (strings), aiHotspot (boolean). |
rules | array | Optional | Each rule needs processingConfigs (object). |
rules[].conditions | array | Optional | Each condition needs column_name, condition (equals, contains, starts_with, ends_with) and value. |
customIntegration | object | Optional | Partner add-on selector, for example { "evox": { "condition": "new" } }. Converted into customIntegrations. |
poc_name, poc_email, poc_contact | string | Optional | Passed to the partner onboarding request. Not stored on the workflow. |
Fields not in the workflow schema (for example partnerName, logo, approved) are not stored.
- Authenticate: set
Authorization: Bearer YOUR_TOKEN. - Identify the feed: send
name,partnerId,dealerId,teamIdandenterpriseId. - Mark it as inventory: send
partnerProviderTypes: ["IMS"]. - Thresholds: send
-1(disabled) or a positive number, never0. - Finish: on success, mark the checklist task
IMS Integrationdone.
Sample request
curl -X POST "https://api.spyne.ai/partner/input-workflow" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Example Inventory Feed - Inventory Provider",
"partnerId": "<partnerId>",
"dealerId": "<dealerId>",
"enterpriseId": "<enterpriseId>",
"teamId": "<teamId>",
"isActive": true,
"createDraft": true,
"partnerProviderTypes": ["IMS"],
"thresholdCounts": { "newCars": -1, "usedCars": -1 },
"preliminaryConfigs": { "enabled": false, "thresholds": { "new": -1, "used": -1 } }
}'import requests
res = requests.post(
"https://api.spyne.ai/partner/input-workflow",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={
"name": "Example Inventory Feed - Inventory Provider",
"partnerId": "<partnerId>",
"dealerId": "<dealerId>",
"enterpriseId": "<enterpriseId>",
"teamId": "<teamId>",
"partnerProviderTypes": ["IMS"],
"thresholdCounts": {"newCars": -1, "usedCars": -1},
},
)
if res.status_code == 409:
pass # a workflow already exists for this partnerId + dealerId; update it instead
workflow = res.json().get("data")const res = await fetch("https://api.spyne.ai/partner/input-workflow", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_TOKEN",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Example Inventory Feed - Inventory Provider",
partnerId: "<partnerId>",
dealerId: "<dealerId>",
enterpriseId: "<enterpriseId>",
teamId: "<teamId>",
partnerProviderTypes: ["IMS"],
thresholdCounts: { newCars: -1, usedCars: -1 },
}),
});
const body = await res.json();Sample response
{
"success": true,
"message": "Input workflow created successfully",
"data": {
"_id": "<workflowId>",
"name": "Example Inventory Feed - Inventory Provider",
"enterpriseId": "<enterpriseId>",
"teamId": "<teamId>",
"userId": "<userId>",
"partnerId": "<partnerId>",
"dealerId": "<dealerId>",
"isActive": true,
"createDraft": true,
"reseller": false,
"partnerProviderTypes": ["IMS"],
"thresholdCounts": { "newCars": -1, "usedCars": -1 },
"rules": [],
"latestFileUpload": null,
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z"
}
}{ "success": false, "message": "Validation failed", "errors": ["Partner ID is required", "Dealer ID is required"] }{ "success": false, "message": "Failed to create input workflow", "error": "Failed to fetch userId for the provided enterpriseId" }{ "success": false, "error": "Invalid Authentication" }{
"success": false,
"message": "Failed to create input workflow",
"error": "Input workflow with the same partnerId and dealerId already exists",
"isPresent": true
}{ "success": false, "message": "Failed to create input workflow", "error": "<error message>" }Response parameters
| Parameter | Type | Description |
|---|---|---|
success | boolean | true on 201. |
message | string | Result message. |
data | object | The created workflow with rules and latestFileUpload. Same fields as List inventory feed workflows. |
isPresent | boolean | On 409 only. A workflow for this partnerId + dealerId already exists. |
Errors
| Status | Code | When it happens |
|---|---|---|
400 | Validation failed | Missing name, partnerId, dealerId or teamId; invalid or unknown partnerId; a threshold is 0 or not a number; bad productOptions; bad rules or conditions. |
400 | Failed to fetch userId for the provided enterpriseId | enterpriseId was sent and the owner user could not be found or looked up. |
401 | Authentication token required or Invalid Authentication | Missing or rejected token. |
409 | isPresent: true | A non-reseller workflow with the same partnerId + dealerId exists. |
500 | Failed to create input workflow | Database or other error. If saving rules fails, the workflow itself may already be saved. |
What happens next
Store the returned _id and use Update an inventory feed workflow for later edits. On 409, find the existing workflow with List inventory feed workflows (partnerId + dealerId) and update it. After a successful IMS save, the UI calls Mark a checklist task done in the Checklist section with taskName: "IMS Integration".
Updated about 1 hour ago
