Nexon | 2022-11-29 03:57:20 UTC | #1
Hello, When making a request to /api/v2/users we are receiving objects that do not adhere to the swagger contract,
"User": {
"type": "object",
"required": [
"version"
],
"properties": {
"id": {
"type": "string",
"description": "The globally unique identifier for the object.",
"readOnly": true
},
"name": {
"type": "string"
},
"division": {
"description": "The division to which this entity belongs.",
"$ref": "#/definitions/Division"
},
"chat": {
"$ref": "#/definitions/Chat"
},
"department": {
"type": "string"
},
"email": {
"type": "string"
},
"primaryContactInfo": {
"type": "array",
"description": "Auto populated from addresses.",
"readOnly": true,
"items": {
"$ref": "#/definitions/Contact"
}
},
"addresses": {
"type": "array",
"description": "Email addresses and phone numbers for this user",
"items": {
"$ref": "#/definitions/Contact"
}
},
"state": {
"type": "string",
"description": "The current state for this user.",
"readOnly": true,
"enum": [
"active",
"inactive",
"deleted"
]
},
"title": {
"type": "string"
},
"username": {
"type": "string"
},
"manager": {
"$ref": "#/definitions/User"
},
"images": {
"type": "array",
"items": {
"$ref": "#/definitions/UserImage"
}
},
"version": {
"type": "integer",
"format": "int32",
"description": "Required when updating a user, this value should be the current version of the user. The current version can be obtained with a GET on the user before doing a PATCH."
},
"certifications": {
"type": "array",
"items": {
"type": "string"
}
},
"biography": {
"$ref": "#/definitions/Biography"
},
"employerInfo": {
"$ref": "#/definitions/EmployerInfo"
},
"routingStatus": {
"description": "ACD routing status",
"readOnly": true,
"$ref": "#/definitions/RoutingStatus"
},
"presence": {
"description": "Active presence",
"readOnly": true,
"$ref": "#/definitions/UserPresence"
},
"integrationPresence": {
"description": "Integration presence",
"readOnly": true,
"$ref": "#/definitions/UserPresence"
},
"conversationSummary": {
"description": "Summary of conversion statistics for conversation types.",
"readOnly": true,
"$ref": "#/definitions/UserConversationSummary"
},
"outOfOffice": {
"description": "Determine if out of office is enabled",
"readOnly": true,
"$ref": "#/definitions/OutOfOffice"
},
"geolocation": {
"description": "Current geolocation position",
"readOnly": true,
"$ref": "#/definitions/Geolocation"
},
"station": {
"description": "Effective, default, and last station information",
"readOnly": true,
"$ref": "#/definitions/UserStations"
},
"authorization": {
"description": "Roles and permissions assigned to the user",
"readOnly": true,
"$ref": "#/definitions/UserAuthorization"
},
"profileSkills": {
"type": "array",
"description": "Profile skills possessed by the user",
"readOnly": true,
"items": {
"type": "string"
}
},
"locations": {
"type": "array",
"description": "The user placement at each site location.",
"readOnly": true,
"items": {
"$ref": "#/definitions/Location"
}
},
"groups": {
"type": "array",
"description": "The groups the user is a member of",
"readOnly": true,
"items": {
"$ref": "#/definitions/Group"
}
},
"team": {
"description": "The team the user is a member of",
"readOnly": true,
"$ref": "#/definitions/Team"
},
"skills": {
"type": "array",
"description": "Routing (ACD) skills possessed by the user",
"readOnly": true,
"items": {
"$ref": "#/definitions/UserRoutingSkill"
}
},
"languages": {
"type": "array",
"description": "Routing (ACD) languages possessed by the user",
"readOnly": true,
"items": {
"$ref": "#/definitions/UserRoutingLanguage"
}
},
"acdAutoAnswer": {
"type": "boolean",
"description": "acd auto answer"
},
"languagePreference": {
"type": "string",
"description": "preferred language by the user",
"readOnly": true
},
"lastTokenIssued": {
"$ref": "#/definitions/OAuthLastTokenIssued"
},
"dateLastLogin": {
"type": "string",
"format": "date-time",
"description": "The last time the user logged in using username and password. Date time is represented as an ISO-8601 string. For example: yyyy-MM-ddTHH:mm:ss[.mmm]Z",
"readOnly": true
},
"selfUri": {
"type": "string",
"format": "uri",
"description": "The URI for this object",
"readOnly": true
}
}
}
The swagger dictates that objects of type "user" has to contain a property called "version" and that. they can have an optional field called "manager" which is also of the type "user"
"entities": [
{
"id": "00000000-0000-0000-0000-000000000000",
"name": "[REDACTED]",
"division": {
"id": "00000000-0000-0000-0000-000000000001",
"name": "[REDACTED]",
"selfUri": "/api/v2/authorization/divisions/00000000-0000-0000-0000-000000000001"
},
"chat": {
"jabberId": "000000000000000000000000@[REDACTED].orgspan.com"
},
"email": "[REDACTED]",
"primaryContactInfo": [
{
"address": "[REDACTED]",
"mediaType": "EMAIL",
"type": "PRIMARY"
}
],
"addresses": [],
"state": "active",
"username": "[REDACTED]",
"manager": {
"id": "00000000-0000-0000-0000-000000000002",
"selfUri": "/api/v2/users/00000000-0000-0000-0000-000000000002"
},
"version": 33,
"acdAutoAnswer": false,
"selfUri": "/api/v2/users/00000000-0000-0000-0000-000000000000"
}
]
In the provided example the manager only has an "id" and "selfUri" but the swagger states that a "version" is required as the manager is an object of type "user".
Is the swagger wrong, or are we receiving an incorrect response?
Kind regards
Eos_Rios | 2022-11-29 06:05:55 UTC | #2
The swagger lies, if you look at any SDK they'll tell you version is optional; (question mark after data type means it's nullable/optional)
It may have accidentally been flagged as required because of a misunderstanding of that comment's situational requirement.
But also the swagger lying about what the Manager field even is. That should be a UserReference not a User unless they're planning to add a new Expand parameter to fully flesh Manager out too, but that'd probably be prohibitive due to recursion & redundancy.
References are not self-expanding and generally only contain rudimentary information (id, selfUri, maybe name and/or description) to do your own lookup of the object if you want to know deeper details. They can be seen scattered throughout the code and sometimes are clearly differentiated by their own objects but sometimes just return a partial implementation of their object without warning like this one did.
Division is a better handled example in the Users api, because it clearly points to Division which is a reference rather than AuthzDivision which is the real division data.
Since all the fields are optional anyway and UserReference didn't introduce any fields that User didn't also have it was technically legal for them to map the manager field directly to a user object even though it results in a mostly empty user when deserializing.
system | 2022-12-30 06:06:11 UTC | #3
This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.
This post was migrated from the old Developer Forum.
ref: 17411