Add directory contacts

Adds one or more contacts to the rooftop's employee directory from a JSON list.

POSThttps://api.spyne.ai/console/v1/product-onboarding/vini/directory/manual
AuthBearer token (console user)Rate limitNot documentedProcessingSynchronous. Waits for the directory write (30 s timeout).

Validates each user, then sends the contacts to the directory as one batch:

  • The phone is built as isdCode + phoneNumber and must be a valid number with country code.
  • Contacts that exactly match an existing contact (same department, name, designation, phone and extension) are skipped.
  • If a department is given by name instead of ID, missing departments are created.

The response reports how many users were processed. It does not return the new contact IDs. The call does not update any checklist task.

Before you call it

  • You need enterpriseId and teamId.

  • Get department IDs from the rooftop's department list. The UI matches the department name to an ID. If nothing matches, it sends the name in departmentId, and a name sent there fails (see Errors).

  • All users in one request must use the same kind of department reference: either all IDs or all names.

  • Authentication: Bearer token of a signed-in console user. The token, and any cookie on the request, are forwarded to the directory write.

  • Rate limit: Not documented

  • Processing: Synchronous. Waits for the directory write (30 second timeout).


Request

Requiredalways sendOptionalcan be left out
Request checklist
  1. Each user needs firstName, role, departmentId, isdCode and phoneNumber.
  2. Send isdCode with a leading +, e.g. +1.
  3. On 2xx, call Mark a checklist task done with {teamId, taskName: "Employee Directory", isCompleted: true}.
ParameterTypeRequiredDescription
Headers——Sent as HTTP headers.
AuthorizationstringRequiredBearer YOUR_TOKEN
Content-TypestringRequiredapplication/json
Body——Sent as a JSON body.
enterpriseIdstringRequiredDealer group ID. Without it the call returns 400.
teamIdstringRequiredRooftop ID. Without it the call returns 400.
teamNamestringOptionalSent by the UI. Not used.
usersarrayRequiredNon-empty list of contacts.
users[].firstNamestringRequiredFirst name.
users[].lastNamestringOptionalLast name.
users[].rolestringRequiredJob title. It is stored as designation. designation is accepted in its place.
users[].departmentIdstringRequiredDepartment ID, a positive integer. department_id is also accepted.
users[].isdCodestringRequiredCountry code, e.g. +1.
users[].phoneNumberstringRequiredNumber without country code. phone_number or phone are also accepted.
users[].extensionstringOptionalExtension.
users[].emailstringOptionalEmail.

Sample request

curl -X POST "https://api.spyne.ai/console/v1/product-onboarding/vini/directory/manual" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enterpriseId": "<enterpriseId>",
    "teamId": "<teamId>",
    "teamName": "Example Motors",
    "users": [
      { "firstName": "Jane", "lastName": "Doe", "role": "Service Advisor", "departmentId": "<departmentId>",
        "isdCode": "+1", "phoneNumber": "5550100000", "extension": "204", "email": "[email protected]" }
    ]
  }'
import requests

payload = {
    "enterpriseId": "<enterpriseId>",
    "teamId": "<teamId>",
    "teamName": "Example Motors",
    "users": [{
        "firstName": "Jane", "lastName": "Doe", "role": "Service Advisor",
        "departmentId": "<departmentId>", "isdCode": "+1", "phoneNumber": "5550100000",
        "extension": "204", "email": "[email protected]",
    }],
}
res = requests.post(
    "https://api.spyne.ai/console/v1/product-onboarding/vini/directory/manual",
    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/vini/directory/manual", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_TOKEN", "Content-Type": "application/json" },
  body: JSON.stringify({
    enterpriseId: "<enterpriseId>",
    teamId: "<teamId>",
    teamName: "Example Motors",
    users: [{
      firstName: "Jane", lastName: "Doe", role: "Service Advisor", departmentId: "<departmentId>",
      isdCode: "+1", phoneNumber: "5550100000", extension: "204", email: "[email protected]",
    }],
  }),
});
console.log(res.status, await res.json());

Sample response

{
  "success": true,
  "error": false,
  "message": "Users processed successfully.",
  "data": {
    "totalUsers": 1,
    "invitedUsers": 0,
    "directoryUsers": 1,
    "inviteUsersApiCalled": false,
    "directoryApiCalled": true,
    "inviteUsersStatusCode": null,
    "directoryStatusCode": 200
  }
}
{
  "error": true,
  "message": "Some items are missing required values.",
  "validationErrors": [{ "rowNumber": 1, "missingFields": ["isdCode", "phone_number"] }]
}
{ "message": "Department(s) not found for enterprise/team: 99", "error": true, "code": "ERROR_BAD_REQ_400", "details": null, "data": null }
{ "message": "Invalid Token", "error": true, "code": "ERROR_AUTH_401", "details": "", "data": null }
{ "error": true, "message": "timeout of 30000ms exceeded" }

400 Bad Request (row validation). Other 400 messages from this endpoint:

  • Provide a non-empty array in `users`.
  • enterpriseId and teamId are required for directory creation.

400 Bad Request (directory write, passed through). Other passed-through 400 messages:

  • Invalid entry at index 0. "phone" value "..." must be a valid phone number with country code, e.g. +1<number>
  • Invalid entry at index 0. departmentId must be a valid positive integer
  • All contacts in a request must use either department or departmentId

Response fields

ParameterTypeDescription
successbooleantrue on 200.
data.totalUsersnumberUsers accepted for the directory.
data.directoryUsersnumberSame as totalUsers.
data.directoryApiCalledbooleantrue when the batch was sent.
data.directoryStatusCodenumber or nullStatus of the directory write.
data.invitedUsers, inviteUsersApiCalled, inviteUsersStatusCodenumber / boolean / nullAlways 0, false and null. No console invites are sent from here.

Errors

StatusReasonWhen it happens
400Provide a non-empty array in usersusers is missing or empty.
400Some items are missing required values.A user is missing firstName, role, departmentId, isdCode or the phone. validationErrors lists them by row.
400enterpriseId and teamId are required for directory creation.IDs are missing from the body.
400Passed through from the directory writeInvalid phone, departmentId not a positive integer (for example a department name), a department not on this rooftop, or mixed ID and name references.
401ERROR_AUTH_401Missing or invalid token.
500Unexpected errorThe directory write timed out or failed without a response.

Next

On 2xx, call Mark a checklist task done with {teamId: "<teamId>", taskName: "Employee Directory", isCompleted: true}. The UI does this without waiting for the result. Refresh with List the employee directory. Directory contacts can be picked as the authorized representative on the brand registration.


Did this page help you?