REST API Errors

REST API Errors

UltraCart REST API Errors - Developer's Reference Guide

Table of Contents

  1. Overview

  2. Error Response Structure

  3. HTTP Status Codes

  4. Authentication Errors

  5. Validation Errors

  6. Rate Limiting Errors

  7. Cart and Checkout Errors

  8. Payment Processing Errors

  9. Resource Errors

  10. Server Errors

  11. Troubleshooting Tips

  12. Best Practices


Overview

The UltraCart REST API uses standard HTTP status codes and returns structured error messages to help developers diagnose and resolve issues. This guide covers both the legacy REST API (Version 1) and the current REST API (Version 2).

API Base URLs:

  • Version 2: https://secure.ultracart.com/rest/v2

  • Version 1 (Legacy): https://secure.ultracart.com/rest

Important Note: Version 1 is legacy and maintained only for backward compatibility. All new development should use Version 2 with the official SDKs.


Error Response Structure

Version 2 Error Format

All API responses in Version 2 include an error object when errors occur:

{ "error": { "developer_message": "Detailed technical error message for developers", "user_message": "User-friendly error message suitable for display" }, "metadata": {} }

Key Fields:

  • developer_message: Technical details for debugging (log this for troubleshooting)

  • user_message: Customer-facing message (safe to display to end users)

  • metadata: Additional context about the error (optional)

Example Error Handling (Multiple Languages)

PHP:

$api_response = $order_api->getOrder($order_id, $expansion); if ($api_response->getError() != null) { error_log($api_response->getError()->getDeveloperMessage()); error_log($api_response->getError()->getUserMessage()); exit(); }

Python:

api_response = order_api.get_order(order_id, expand=expand) if api_response.error: print(f"Developer Message: {api_response.error.developer_message}") print(f"User Message: {api_response.error.user_message}") exit()

JavaScript/TypeScript:

const apiResponse = await orderApi.getOrder({orderId, expand: expansion}); if (apiResponse.error) { console.error('Developer Message:', apiResponse.error.developer_message); console.error('User Message:', apiResponse.error.user_message); throw new Error('Failed to retrieve order'); }

C#:

OrderResponse apiResponse = orderApi.GetOrder(orderId, expansion); if (apiResponse.Error != null) { Console.Error.WriteLine(apiResponse.Error.DeveloperMessage); Console.Error.WriteLine(apiResponse.Error.UserMessage); Environment.Exit(1); }

Ruby:

api_response = order_api.get_orders_batch( order_query_batch: order_batch, opts: { '_expand' => expansion } ) if api_response.error warn "Developer Message: #{api_response.error.developer_message}" warn "User Message: #{api_response.error.user_message}" exit 1 end

Version 1 Error Format

Version 1 returns errors as an array in the errors field:

{ "errors": [ "Error message 1", "Error message 2" ] }

Validation Errors:

{ "validationErrors": [ { "field": "email", "message": "Email address is required" } ] }

HTTP Status Codes

2xx Success Codes

Code

Status

Description

Code

Status

Description

200

OK

Request succeeded, response contains data

201

Created

Resource created successfully

204

No Content

Request succeeded, no content in response (e.g., delete operations)

4xx Client Error Codes

Code

Status

Description

Common Causes

Code

Status

Description

Common Causes

400

Bad Request

Malformed request syntax or invalid parameters

Invalid JSON, missing required fields, incorrect data types

401

Unauthorized

Authentication required or failed

Missing/invalid API key, expired OAuth token, insufficient permissions

403

Forbidden

Valid request but server refuses to respond

Permission denied, API access not enabled for user, IP restriction

404

Not Found

Resource does not exist

Invalid order ID, item ID, or endpoint URL; typos in URL

405

Method Not Allowed

HTTP method not supported for endpoint

Using GET instead of POST, or vice versa

422

Unprocessable Entity

Request well-formed but contains semantic errors

Invalid field values, failed business logic validation

429

Too Many Requests

Rate limit exceeded

Making too many requests in a short time period

5xx Server Error Codes

Code

Status

Description

Action

Code

Status

Description

Action

500

Internal Server Error

Unexpected server-side error

Retry with exponential backoff, contact support if persists

502

Bad Gateway

Invalid response from upstream server

Temporary issue, retry after delay

503

Service Unavailable

Server temporarily unavailable

System maintenance or overload, retry after delay

504

Gateway Timeout

Gateway did not receive timely response

Retry request, check for long-running operations


Authentication Errors

Missing Merchant ID

Error Message: "Missing Merchant ID"

Cause: The merchant ID was not provided in the request.

Solution: Provide merchant ID using one of these methods:

  1. Query Parameter:

    ?_mid=YOUR_MERCHANT_ID
  2. HTTP Header:

    X-UC-Merchant-Id: YOUR_MERCHANT_ID
  3. Cookie:

    UltraCartMerchantID=YOUR_MERCHANT_ID
  4. StoreFront URL (Recommended):

    https://YOUR_MERCHANT_ID.ultracartstore.com/rest/...

Example (jQuery):

jQuery.ajax({ url: '/rest/cart', headers: { 'X-UC-Merchant-Id': 'YOUR_MERCHANT_ID', 'cache-control': 'no-cache' }, dataType: 'json' });

401 Unauthorized - Permission Denied

HTTP Status: 401
Error Response:

{ "error": { "developer_message": "Permission Denied.", "user_message": "Permission Denied." }, "metadata": {} }

Common Causes:

  1. Invalid or missing API key

  2. API key doesn't have required permissions

  3. Using Simple API Key where OAuth is required

  4. API access not enabled for the user account

Solutions:

For Simple API Key:

// PHP $api_key = "YOUR_SIMPLE_API_KEY"; ultracart\v2\Configuration::getDefaultConfiguration() ->setApiKey('x-ultracart-simple-key', $api_key);
# Python from ultracart.configuration import Configuration configuration = Configuration() configuration.api_key['x-ultracart-simple-key'] = 'YOUR_SIMPLE_API_KEY'

Enable API Access:

  1. Log into secure.ultracart.com

  2. Navigate to: Configuration → Manage Users → Edit User

  3. Check "API Access" permission

  4. Save changes

For OAuth Applications:

  • Ensure valid access token

  • Verify OAuth scopes match endpoint requirements

  • Check if token has expired and refresh if needed

Invalid API Credentials

Error Message: "Invalid credentials"

Cause: API key is incorrect or has been revoked.

Solution:

  1. Verify API key in UltraCart admin panel

  2. Regenerate API key if compromised

  3. Check for extra spaces when copying API key

  4. Ensure using correct environment (production vs. sandbox)


Validation Errors

400 Bad Request - Invalid JSON

Error Message: "Problems parsing JSON"

Cause: Request body contains malformed JSON.

Solutions:

  1. Validate JSON syntax using a linter or validator

  2. Ensure proper escaping of special characters

  3. Check for trailing commas (not allowed in JSON)

  4. Verify content-type header is set correctly

// Correct content-type header headers: { 'Content-Type': 'application/json; charset=UTF-8' }

400 Bad Request - Body Not a JSON Object

Error Message: "Body should be a JSON object"

Cause: Request body is not formatted as a JSON object.

Solution: Ensure request body is a valid JSON object:

// Incorrect - sending string data: "some string" // Correct - sending JSON object data: JSON.stringify({ merchantId: 'DEMO', email: 'customer@example.com' })

422 Unprocessable Entity - Invalid Parameters

Error Message: "Invalid request" or "Invalid input"

Common Scenarios:

  1. Wrong parameter type:

// Error: Expecting string but got array { "item_id": ["ITEM1", "ITEM2"] // Should be: "ITEM1" }
  1. Missing required fields:

// Error: Missing required email field { "firstName": "John", "lastName": "Doe" // email is required }
  1. Invalid field values:

// Error: Invalid credit card expiration { "creditCardExpirationMonth": 13 // Should be 1-12 }

Solution: Refer to API documentation for correct parameter types and required fields.

Cart Validation Errors

The /rest/cart/validate endpoint returns specific validation errors:

Request:

jQuery.ajax({ url: '/rest/cart/validate?check=billing&check=shipping&check=payment', type: 'POST', contentType: 'application/json; charset=UTF-8', data: JSON.stringify(cart), dataType: 'json' });

Response (with errors):

[ "Email address is required", "Billing first name is required", "Credit card number is invalid" ]

Common Validation Checks:

  • billing - Billing address fields

  • shipping - Shipping address fields

  • payment - Payment method and card details

  • items - Cart items validity

  • coupons - Coupon code validity

  • giftCertificate - Gift certificate validation


Rate Limiting Errors

429 Too Many Requests

HTTP Status: 429
Headers Returned:

Retry-After: 60

Error Response:

{ "error": { "developer_message": "Rate limit exceeded. Please retry after 60 seconds.", "user_message": "Too many requests. Please try again later." } }

Rate Limits:

Endpoint Type

Rate Limit

Notes

Endpoint Type

Rate Limit

Notes

Most endpoints

Varies by endpoint

Standard rate limiting

Item inventory (GET /items/inventory)

Max 1 call per 15 minutes

Strictly enforced

Batch operations

500 items max per request

Exceeding returns 400 error

SDK Auto-Retry (PHP): The PHP SDK automatically retries when rate limits are hit:

// PHP SDK handles retry automatically when rate limit triggered // Other SDKs to follow in future updates

Manual Retry Logic:

JavaScript:

async function retryRequest(requestFunc, maxRetries = 5) { for (let attempt = 0; attempt < maxRetries; attempt++) { try { const response = await requestFunc(); if (response.status !== 429) { return response; } // Get retry-after header if present const retryAfter = response.headers.get('Retry-After'); const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000; await new Promise(resolve => setTimeout(resolve, delay)); } catch (error) { if (attempt === maxRetries - 1) throw error; } } throw new Error('Max retries exceeded'); }

Python:

import time import random def retry_request(request_func, max_retries=5): for attempt in range(max_retries): try: response = request_func() if response.status_code != 429: return response retry_after = response.headers.get('Retry-After') delay = int(retry_after) if retry_after else (2 ** attempt) time.sleep(delay + random.uniform(0, 1)) except Exception as e: if attempt == max_retries - 1: raise e raise Exception("Max retries exceeded")

Best Practices:

  1. Implement exponential backoff with jitter

  2. Honor Retry-After header when present

  3. Cache frequently accessed data (items, allowed countries)

  4. Batch requests when possible

  5. Monitor API usage patterns


Cart and Checkout Errors

Missing Checkout Redirect

Common Mistake: Not redirecting to redirectToUrl after checkout.

Error: Order never completes, payment not processed.

Explanation: The /rest/cart/checkout endpoint is NOT the final step. After calling checkout successfully (no errors in response), you must redirect the browser to the URL found in checkoutResponse.redirectToUrl.

Correct Flow:

jQuery.ajax({ url: '/rest/cart/checkout', type: 'POST', contentType: 'application/json; charset=UTF-8', data: JSON.stringify(checkoutRequest), dataType: 'json' }).done(function(checkoutResponse) { if (!checkoutResponse.errors || checkoutResponse.errors.length === 0) { // CRITICAL: Must redirect to complete order window.location.href = checkoutResponse.redirectToUrl; } else { // Display errors to user displayErrors(checkoutResponse.errors); } });

What happens during redirect:

  • Payment gateway processing

  • Fraud screening

  • Upsell gauntlet (if configured)

  • Order finalization

  • Receipt generation

If errors occur during redirect phase:

  • User is redirected back to checkoutRequest.redirectOnErrorUrl

  • This is typically your checkout page

  • Error details are in URL parameters or session

Preorder Item Errors Overriding Other Errors

Issue: When cart contains preorder items, preorder warnings may hide validation errors.

Solution: Separate cart updates from checkout calls:

// Step 1: Update cart with items jQuery.ajax({ url: '/rest/cart', type: 'PUT', data: JSON.stringify(cart), // ... }).done(function(updatedCart) { // Step 2: Then call checkout jQuery.ajax({ url: '/rest/cart/checkout', type: 'POST', data: JSON.stringify(checkoutRequest), // ... }); });

Hosted Fields Required (PCI 3.0)

Error Context: As of June 2015, credit card numbers cannot be sent directly to the API.

Solution: Use UltraCart Hosted Fields for PCI 3.0 compliance.

Old (No longer works):

cart.creditCardNumber = '4111111111111111'; // ❌ Not allowed

Correct (Hosted Fields):

// 1. Load Hosted Fields library <script src="https://token.ultracart.com/hosted_fields/..."></script> // 2. Initialize Hosted Fields UltraCart.HostedFields.initialize({ // configuration }); // 3. Tokenize card before checkout UltraCart.HostedFields.tokenize(function(token) { cart.creditCardToken = token; // ✅ Use token instead // Proceed with checkout });

Cart Session Expiration

Symptom: Cart ID becomes invalid, causing 404 errors.

Cause: Cart sessions expire after inactivity.

Solution:

  1. Store cartId in browser cookie

  2. Create new cart if existing cart returns 404

  3. Implement cart recovery for logged-in customers

function getOrCreateCart() { const savedCartId = getCookie('UltraCartCartId'); if (savedCartId) { // Try to retrieve existing cart return fetchCart(savedCartId).catch(error => { if (error.status === 404) { // Cart expired, create new one return createNewCart(); } throw error; }); } return createNewCart(); }

Arbitrary Unit Cost Errors

Error: Using arbitraryUnitCost on items not configured for it.

Cause: Item must be configured in UltraCart admin to allow arbitrary pricing.

Solution:

  1. Configure item in admin: Items → Edit Item → Pricing

  2. Enable "Allow Arbitrary Unit Cost"

  3. Set min/max bounds if needed

// Now this will work { "item_id": "DONATION", "quantity": 1, "arbitraryUnitCost": 50.00 }

Distribution Center Not Configured for REST API

HTTP Status: 400
Headers:

HTTP/1.1 400 X-UltraCart-Request-Id: 8376DD8AC3EA6A019A4ADA5E291F43489 Content-Type: application/json; charset=UTF-8 UC-REST-ERROR: Distribution center is not configured for REST API transport.

Error Response:

{ "error": { "developer_message": "Distribution center is not configured for REST API transport.", "user_message": "Distribution center is not configured for REST API transport." }, "metadata": {} }

Cause: The distribution center is not properly configured to use REST API as its transmission mechanism.

Solution:

Step 1: Navigate to Distribution Center Settings

  1. Log into secure.ultracart.com

  2. Go to: Configuration → Checkout → Shipping → Distribution Centers

    • Direct URL: https://secure.ultracart.com/merchant/configuration/shipping/distributionCenterListLoad.do

  3. Click Edit next to the distribution center

Step 2: Verify Basic Configuration In the Distribution Center tab, ensure these required fields are filled:

  • Code

  • Name

  • Postal Code

  • State

  • Country

Step 3: Configure Transmission Mechanism

  1. Click on the Transmission Mechanism tab

  2. Set Transmission Method to: REST

  3. In the Authorized Application (required) dropdown:

    • Select your authorized OAuth application

    • This links your API application to the distribution center

  4. Important: Scroll to bottom and click Save

Step 4: Verify Configuration After saving, the distribution center should now accept REST API calls for:

  • Order creation via REST

  • Order status updates

  • Shipping notifications

  • Inventory management

Common Mistakes:

  • Forgetting to save after changing transmission method

  • Not having an authorized OAuth application created yet

  • Selecting wrong application from dropdown

  • Missing required fields in Distribution Center tab (prevents saving)

Create Authorized Application (if needed):

  1. Navigate to: Configuration → OAuth Applications

  2. Create new OAuth application

  3. Grant necessary permissions (orders, shipping, etc.)

  4. Return to Distribution Center settings

  5. Select newly created application from dropdown

Verification Test:

// Test if distribution center is properly configured // Attempt to create or update an order via REST API // Should succeed without the 400 error

Related Errors:

  • If you haven't created an OAuth application yet, the "Authorized Application" dropdown will be empty

  • If the distribution center basic info is incomplete, you won't be able to save the transmission mechanism settings


Payment Processing Errors

These errors occur during the redirect phase after /rest/cart/checkout:

Credit Card Declined

User Message: "Your card was declined. Please use a different payment method."

Common Reasons:

  • Insufficient funds

  • Incorrect billing address (AVS mismatch)

  • Card expired

  • Card reported lost/stolen

  • Incorrect CVV

User Action: User is redirected back to redirectOnErrorUrl to try again.

Payment Gateway Timeout

Symptom: Order processing takes unusually long, then fails.