Skip to content

Errors & Troubleshooting

Every response from the SMBcrm API uses a standard HTTP status code, and every error response adds a small JSON body describing what went wrong. This page lists the status codes you’ll see, the shape of that body, and the fix for the problems developers hit most often.

Status Meaning Typical cause
200 OK / 201 Created Success The request completed; 201 comes back when a resource was created.
400 Bad Request Malformed request Invalid JSON, a parameter of the wrong type, or a malformed query string.
401 Unauthorized Not authenticated Missing, invalid, or expired token, or a missing Version header.
403 Forbidden Not authorized The token is valid but doesn’t have the scope this endpoint requires.
404 Not Found No such resource The ID doesn’t exist, belongs to a different account/location, or was deleted.
409 Conflict Conflicting state The request conflicts with the resource’s current state, for example, a duplicate.
422 Unprocessable Entity Validation error The JSON is well-formed but fails validation: a required field is missing or invalid.
429 Too Many Requests Rate limited You’ve exceeded the account’s burst or daily rate limit.
5xx Server error Something went wrong on SMBcrm’s side. Safe to retry with backoff.

Error responses are JSON, with a status code, a human-readable message, and the standard HTTP error name:

Error response shape
{
"statusCode": 422,
"message": "locationId is required",
"error": "Unprocessable Entity"
}

Start with the two things every request needs:

  1. The Authorization header is present and correctly formatted: Authorization: Bearer <token>, with a real token in place of the placeholder and no extra quotes or surrounding whitespace.
  2. The Version header is present: Version: v3. A request missing this header can be rejected before your token is even checked.
Terminal window
curl -i https://services.smbcrm.com/contacts/<contact_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"

If both headers are correct, the token itself is the problem.

A 403 means authentication succeeded but authorization didn’t. The token is valid, but it wasn’t issued with the scope this endpoint requires. Every endpoint in this reference lists its required scope in the scope field of its endpoint block.

Fix it at the source of the token:

  • Private Integration Token: generate a new one with the missing scope added.
  • OAuth: re-run authorization requesting the additional scope; the user sees it on the consent screen.

See Scopes for the full list of scopes and what each one grants.

The request reached the API and parsed as JSON, but failed validation. Read message first: it names what’s wrong. The most common causes are:

  • A required field is missing, most often locationId.
  • A field has the wrong type or format, for example, a date that isn’t ISO 8601, or a phone number without a country code.
  • A value doesn’t match what the endpoint expects, such as an invalid ID reference or an out-of-range option.

Compare your request body against the example on the endpoint’s own page and confirm every required field is present before you retry.

You’ve exceeded the account’s rate limit. Back off before retrying: resending immediately just extends the throttling window.

Every response carries your current rate-limit status in its headers, so you can slow down proactively instead of reacting after a 429. See Base URL & Headers for the full list of rate-limit headers and how to read them. Where an endpoint supports it, batch requests, cache values that rarely change, and prefer webhooks over polling.

If a request works from your server but fails from browser JavaScript with a CORS error (or no response at all), that’s the gateway’s cross-origin policy, not your token. Call the API from your server instead. This also keeps the token out of client-side code, which you should be doing regardless. See Token Safety.

  • 400 Bad Request: usually malformed JSON or a parameter of the wrong type; validate the request body before it’s sent.
  • 404 Not Found: double-check the ID in the path and confirm it belongs to the account/location your token is scoped to.
  • 409 Conflict: the request conflicts with the resource’s current state, for example creating a duplicate; re-fetch the resource and reconcile before retrying.
  • 5xx: transient; retry with backoff. If it persists, gather the details below before you reach out.

When a request doesn’t behave the way you expect, capture these before you dig further:

  1. The response status and full body. The message field almost always tells you exactly what’s wrong, so don’t rely on the status code alone.
  2. Any request or trace identifier header on the response, if one is present. Include it if you need to escalate.
  3. The base URL and Version header you actually sent. A surprising number of errors turn out to be a typo’d host or a missing header, not a real API problem.
Terminal window
curl -i https://services.smbcrm.com/contacts/<contact_id> \
-H "Authorization: Bearer <token>" \
-H "Version: v3"

-i (cURL) and logging res.status next to the parsed body (Node.js) both surface the real status line, even on responses your JSON client would otherwise swallow on error.

  • Base URL & Headers: required headers, versioning, and the full list of rate-limit response headers.
  • Scopes: the scope each endpoint needs, and how to add one to an existing token.
  • OAuth (account access): refresh an expired access token.
  • Token Safety: call the API server-side instead of from the browser.