Skip to content
Last updated

Error Handling

Learn how to handle errors and HTTP status codes in the MVMNT API.

HTTP Status Codes

The MVMNT API uses standard HTTP status codes to indicate the success or failure of requests.

Success Codes

CodeNameUsage
200OKGET, PATCH, and POST /filter operations succeeded
201CreatedPOST (create) operations succeeded
204No ContentDELETE operations succeeded (no response body)

Success Response Examples

201 Created (POST)

POST /v1/vendors

Response:

HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "friendlyId": "V100001",
  "name": "ABC Warehouse Services",
  "status": "ACTIVE",
  ...
}

200 OK (GET)

GET /v1/vendors/550e8400-e29b-41d4-a716-446655440000

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "friendlyId": "V100001",
  "name": "ABC Warehouse Services",
  ...
}

200 OK (PATCH)

PATCH /v1/vendors/550e8400-e29b-41d4-a716-446655440000

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "friendlyId": "V100001",
  "name": "ABC Warehouse Services Updated",
  ...
}

204 No Content (DELETE)

DELETE /v1/vendors/550e8400-e29b-41d4-a716-446655440000

Response:

HTTP/1.1 204 No Content

No response body is returned for successful DELETE operations.

Client Error Codes (4xx)

These errors indicate a problem with the request.

CodeNameMeaning
400Bad RequestInvalid request format or parameters
401UnauthorizedInvalid or missing authentication token
404Not FoundResource not found
409ConflictDuplicate key or constraint violation
422Unprocessable EntityValidation error
429Too Many RequestsRate limit exceeded

Server Error Codes (5xx)

These errors indicate a problem with the MVMNT API servers.

CodeNameMeaning
500Internal Server ErrorUnexpected server error
503Service UnavailableAPI temporarily unavailable (maintenance, etc.)

Error Response Format

All error responses include a JSON body with details about the error:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      }
    ]
  }
}

Error Response Fields

FieldTypeDescription
error.codestringMachine-readable error code
error.messagestringHuman-readable error message
error.detailsarrayAdditional error details (optional)
error.details[].fieldstringField name that caused the error
error.details[].messagestringField-specific error message

Common Errors

400 Bad Request

Cause: Malformed request, invalid JSON, or missing required fields

Example:

{
  "error": {
    "code": "BAD_REQUEST",
    "message": "Invalid JSON in request body"
  }
}

Solution:

  • Verify JSON syntax is correct
  • Check that all required fields are included
  • Ensure field types match the API specification

401 Unauthorized

Cause: Missing, expired, or invalid authentication token

Example:

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired access token"
  }
}

Solution:

  • Obtain a new access token using /oauth2/token
  • Include Authorization: Bearer {token} header in all requests
  • Check that your client ID and secret are correct

404 Not Found

Cause: Resource with the specified ID does not exist

Example:

{
  "error": {
    "code": "NOT_FOUND",
    "message": "Vendor not found"
  }
}

Solution:

  • Verify the resource ID is correct
  • Check that the resource hasn't been deleted (see Soft Deletes)
  • Use filter endpoints to find resources by other criteria

409 Conflict

Cause: Duplicate client key or constraint violation

Example:

{
  "error": {
    "code": "DUPLICATE_KEY",
    "message": "A vendor with this key already exists",
    "details": [
      {
        "field": "key",
        "message": "Key 'ERP-VENDOR-123' is already in use"
      }
    ]
  }
}

Solution:

  • Use a different, unique client key
  • Check if the resource already exists using the key
  • For updates, use PATCH instead of POST

422 Unprocessable Entity

Cause: Request is valid but contains semantic errors (validation failures)

Example:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format"
      },
      {
        "field": "phone",
        "message": "Phone number is required"
      }
    ]
  }
}

Solution:

  • Review the details array for specific field errors
  • Fix each validation error listed
  • Consult the API reference for field requirements

429 Too Many Requests

Cause: Rate limit exceeded

Example:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again in 30 seconds."
  }
}

Response Headers:

  • X-RateLimit-Limit: Your maximum requests per minute
  • X-RateLimit-Remaining: Requests remaining in current window
  • X-RateLimit-Reset: Unix timestamp when limit resets

Solution:

  • Implement exponential backoff
  • Reduce request frequency
  • Batch operations where possible
  • Contact support to increase rate limits

500 Internal Server Error

Cause: Unexpected error on the MVMNT API servers

Example:

{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An unexpected error occurred"
  }
}

Solution:

  • Retry the request with exponential backoff
  • If the error persists, contact support with the request details
  • Check the status page for known issues

Error Handling Best Practices

✅ Do

  • Check HTTP status codes: Always check the status code before processing the response
  • Handle all error types: Implement handlers for all possible error codes
  • Parse error details: Use the error.details array for field-specific validation errors
  • Implement retries: Use exponential backoff for transient errors (500, 503, 429)
  • Log error responses: Log the full error response for debugging
  • Show user-friendly messages: Translate technical errors into user-friendly messages

❌ Don't

  • Don't retry 4xx errors: Client errors won't succeed on retry (except 429)
  • Don't ignore error details: The details array contains important field-level information
  • Don't retry immediately: Use exponential backoff to avoid overwhelming the API
  • Don't expose raw errors to users: Translate technical errors into user-friendly messages
  • Don't continue on 401 errors: Obtain a new token before retrying

Retry Strategies

Exponential Backoff

For transient errors (500, 503, 429), implement exponential backoff:

async function requestWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);

      // Success - return response
      if (response.ok) {
        return response;
      }

      // Client errors (4xx) - don't retry (except 429)
      if (response.status >= 400 && response.status < 500) {
        if (response.status === 429) {
          // Rate limit - use exponential backoff
          const backoffMs = Math.pow(2, attempt) * 1000;
          await new Promise((resolve) => setTimeout(resolve, backoffMs));
          continue;
        }
        // Other 4xx errors - throw immediately
        throw new Error(`Client error: ${response.status}`);
      }

      // Server errors (5xx) - retry with backoff
      if (response.status >= 500) {
        const backoffMs = Math.pow(2, attempt) * 1000;
        await new Promise((resolve) => setTimeout(resolve, backoffMs));
        continue;
      }
    } catch (error) {
      // Network error - retry with backoff
      if (attempt < maxRetries - 1) {
        const backoffMs = Math.pow(2, attempt) * 1000;
        await new Promise((resolve) => setTimeout(resolve, backoffMs));
        continue;
      }
      throw error;
    }
  }

  throw new Error('Max retries exceeded');
}

Python Example

import time
import requests
from typing import Optional

def request_with_retry(
    url: str,
    method: str = 'GET',
    max_retries: int = 3,
    **kwargs
) -> requests.Response:
    """Make HTTP request with exponential backoff retry"""
    for attempt in range(max_retries):
        try:
            response = requests.request(method, url, **kwargs)

            # Success
            if response.ok:
                return response

            # Client errors - don't retry (except 429)
            if 400 <= response.status_code < 500:
                if response.status_code == 429:
                    # Rate limit - use exponential backoff
                    backoff_seconds = 2 ** attempt
                    time.sleep(backoff_seconds)
                    continue
                # Other 4xx errors - raise immediately
                response.raise_for_status()

            # Server errors - retry with backoff
            if response.status_code >= 500:
                backoff_seconds = 2 ** attempt
                time.sleep(backoff_seconds)
                continue

        except requests.RequestException as e:
            # Network error - retry with backoff
            if attempt < max_retries - 1:
                backoff_seconds = 2 ** attempt
                time.sleep(backoff_seconds)
                continue
            raise

    raise Exception('Max retries exceeded')

Debugging Tips

1. Log Full Request and Response

Always log the complete request and response for debugging:

console.error('Request failed:', {
  url: request.url,
  method: request.method,
  headers: request.headers,
  body: request.body,
  status: response.status,
  statusText: response.statusText,
  responseBody: await response.text(),
});

2. Check Response Headers

Useful headers for debugging:

  • X-Request-Id: Unique request identifier for support
  • X-RateLimit-*: Rate limit information
  • Content-Type: Response content type

3. Validate Request Before Sending

Validate your request locally before sending:

function validateVendorInput(vendor) {
  const errors = [];

  if (!vendor.name) {
    errors.push({ field: 'name', message: 'Name is required' });
  }

  if (vendor.email && !isValidEmail(vendor.email)) {
    errors.push({ field: 'email', message: 'Invalid email format' });
  }

  if (errors.length > 0) {
    throw new ValidationError('Invalid input', errors);
  }
}

4. Test Error Scenarios

Test your error handling with various scenarios:

  • Invalid authentication token (401)
  • Nonexistent resource ID (404)
  • Duplicate client key (409)
  • Invalid field values (422)
  • Rate limit exceeded (429)

Next Steps