Read the response envelope
Most responses, successful or not, share one envelope. isSuccess is true only when errors is empty, message carries a short summary, and data holds the result. Check isSuccess before reading data.
{
"errors": [
{ "propertyName": "CompanyName", "errorMessage": "Company name is required." }
],
"isSuccess": false,
"message": "Validation failed.",
"data": null
}Each entry in errors has a propertyName and an errorMessage. For a validation failure, propertyName names the field and errorMessage is text you can show to a dealer user. Validation rules for some fields are configured per dealership, so treat errors as the source of truth instead of hard-coding which fields can be rejected.
Error codes
When an error isn't tied to a field, propertyName holds a code that matches the HTTP status.
Responses without the envelope
Three kinds of failure happen before crmSeries can build the envelope, so handle them by status code:
- 401 or 403 with an empty body means the credential itself was rejected: missing, expired, malformed, or not allowed for this operation. A bearer-token 401 includes a WWW-Authenticate header with the reason. See troubleshooting.
- 400 with title and errors as an object means the body couldn’t be read: invalid JSON, or a value of the wrong type, such as text where a number belongs. errors maps each field to a list of messages.
- 500 with an unexpected body can happen when an error isn’t handled. Don’t depend on parsing it; treat the status code as the signal.
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": { "$.phone": ["The JSON value could not be converted to System.String."] },
"traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
}Keep the trace ID
Most responses carry an X-Trace-Id header. Log it with the status code and the operation path for every failed request. When you contact crmSeries, the trace ID lets the team find your exact request.
Retry thoughtfully
Be careful with writes. crmSeries doesn't support idempotency keys, so a create request that timed out may already have succeeded. Before replaying it, check whether the record exists, or use an operation that matches records by your system's own identifier.
crmSeries doesn't currently limit request rates. Build your client to handle a 429 status anyway: wait for the number of seconds in the Retry-After header before trying again.