Testing & Debugging REST APIs
This guide covers how to test and debug Bagisto REST API endpoints using various tools and methods.
API Configuration
The documentation uses centralized API configuration. Update these URLs in .vitepress/theme/config/api.config.ts:
// REST API Base URL
export const REST_API_URL = 'http://127.0.0.1:8000'
// GraphQL API Base URL
export const GRAPHQL_API_URL = 'http://127.0.0.1:8000'Replace with your actual Bagisto instance URLs, and all documentation examples will automatically use the updated URLs.
Interactive Testing Tools
1. Swagger UI (Built-in)
The fastest way to test REST APIs! Bagisto includes Swagger UI for interactive API documentation.
Access Swagger UI:
http://your-domain.com/api/docsFeatures:
- ✅ Try API requests directly from the browser
- ✅ Automatic token/authentication handling
- ✅ Request and response inspection
- ✅ Full endpoint documentation
- ✅ Real-time error messages
Steps to Test:
- Navigate to
/api/docs - Click "Authorize" button (top right)
- Enter your Bearer token or credentials
- Click any endpoint to expand it
- Click "Try it out" button
- Modify parameters as needed
- Click "Execute" to send the request
- View response in the UI
2. ReDoc Alternative
Alternative API documentation viewer:
http://your-domain.com/api/docs.htmlBest for:
- Reading comprehensive endpoint documentation
- Understanding request/response schemas
- Offline documentation reference
3. GraphQL Playground (Same Instance)
If GraphQL is enabled on the same instance:
http://your-domain.com/api/graphqlNote: GraphQL and REST APIs are complementary - use GraphQL for complex queries and mutations, REST APIs for simple CRUD operations.
Testing with cURL
The most reliable method for API testing and CI/CD pipelines.
Basic GET Request
curl -X GET 'http://127.0.0.1:8000/api/shop/locales/1' \
-H 'Accept: application/json'GET with Authentication
curl -X GET 'http://127.0.0.1:8000/api/customer_profiles' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN'POST Request with Body
curl -X POST 'http://127.0.0.1:8000/api/shop/customers/login' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"password": "password123"
}'With Custom Headers
curl -X POST 'http://127.0.0.1:8000/api/shop/add-product-in-cart' \
-H 'Content-Type: application/json' \
-H 'X-Cart-Token: YOUR_CART_TOKEN' \
-H 'Accept-Language: en_US' \
-d '{
"productId": 1,
"quantity": 2
}'Extracting Token from Response
# Login and extract token
TOKEN=$(curl -s -X POST 'http://127.0.0.1:8000/api/shop/customers/login' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"password": "password123"
}' | grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
echo "Token: $TOKEN"
# Use token in subsequent request
curl -X GET 'http://127.0.0.1:8000/api/customer_profiles' \
-H 'Authorization: Bearer '$TOKEN \
-H 'Accept: application/json'Viewing Response Headers
# Show response headers along with body
curl -i -X GET 'http://127.0.0.1:8000/api/shop/products' \
-H 'Accept: application/json'Pretty-Print JSON Response
# Install jq: apt-get install jq (Linux) or brew install jq (Mac)
curl -s -X GET 'http://127.0.0.1:8000/api/shop/products' \
-H 'Accept: application/json' | jqPostman Collection
Setting Up Postman
Import Collection:
- Open Postman
- Click "Import" button
- Paste collection URL or upload JSON file
- Click "Import"
Configure Environment Variables:
- Click "Environments" (left sidebar)
- Click "Create"
- Add variables:
base_url: http://127.0.0.1:8000 access_token: YOUR_TOKEN_HERE cart_token: YOUR_CART_TOKEN_HERE
Run Tests:
- Select environment from dropdown
- Click any request
- Click "Send"
- View response in "Body" tab
Using Variables in Requests:
{{base_url}}/api/shop/products Authorization: Bearer {{access_token}} X-Cart-Token: {{cart_token}}
Insomnia Client
Similar to Postman with a cleaner interface:
Create New Request:
- Click "+" button
- Select HTTP method (GET, POST, etc.)
- Enter URL:
http://127.0.0.1:8000/api/shop/locales/1
Add Headers:
- Click "Header" tab
- Add:
Accept: application/json - Add:
Authorization: Bearer TOKEN
Add Body (for POST/PATCH):
- Click "Body" tab
- Select "JSON" format
- Paste JSON payload
Send Request:
- Click "Send" button
- View response below
JavaScript/Fetch Testing
Use browser console or Node.js to test:
Basic Fetch
// Simple GET request
fetch('http://127.0.0.1:8000/api/shop/locales/1', {
method: 'GET',
headers: {
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));With Authentication
const token = 'YOUR_ACCESS_TOKEN';
fetch('http://127.0.0.1:8000/api/customer_profiles', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
})
.then(response => {
console.log('Status:', response.status);
console.log('Headers:', response.headers);
return response.json();
})
.then(data => console.log('Data:', data))
.catch(error => console.error('Error:', error));POST Request
const payload = {
email: '[email protected]',
password: 'password123'
};
fetch('http://127.0.0.1:8000/api/shop/customers/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(payload)
})
.then(response => response.json())
.then(data => {
console.log('Login Response:', data);
// Extract and store token
const token = data.access_token;
localStorage.setItem('token', token);
})
.catch(error => console.error('Error:', error));Error Handling
async function testAPI(url, options = {}) {
try {
const response = await fetch(url, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
...options.headers
},
...options
});
// Check if response is ok
if (!response.ok) {
const error = await response.json();
throw new Error(`HTTP ${response.status}: ${error.hydra:description || 'Unknown error'}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('API Error:', error.message);
return null;
}
}
// Usage
testAPI('http://127.0.0.1:8000/api/shop/products')
.then(data => console.log(data));Browser Network Inspector
Built-in browser tools for API debugging:
Chrome/Firefox/Edge DevTools
Open DevTools:
- Press
F12orCtrl+Shift+I(Windows/Linux) - Press
Cmd+Option+I(Mac)
- Press
Go to Network Tab:
- Click "Network" tab
- Perform API action in your app
- Find the API request in the list
Inspect Request:
- Click on the request
- View:
- Headers: Request headers and cookies
- Request Body: POST/PATCH data sent
- Response: JSON response from API
- Cookies: Authentication tokens
- Timing: Performance metrics
Copy as cURL:
- Right-click on request
- Select "Copy" > "Copy as cURL"
- Paste in terminal to reproduce issue
Debugging Checklist
When an API request fails, check these items:
✅ Authentication Issues
# Verify token is valid
curl -X GET 'http://127.0.0.1:8000/api/customer_profiles' \
-H 'Authorization: Bearer YOUR_TOKEN'
# Check token expiration
curl -X POST 'http://127.0.0.1:8000/api/shop/refresh-token' \
-H 'Authorization: Bearer YOUR_TOKEN'✅ CORS Issues
# Check if CORS headers are present
curl -i -X OPTIONS 'http://127.0.0.1:8000/api/shop/products' \
-H 'Origin: http://localhost:3000'
# Response should include:
# Access-Control-Allow-Origin: *
# Access-Control-Allow-Methods: GET, POST, PATCH, DELETE✅ Content-Type Issues
# Always include Content-Type for POST/PATCH
curl -X POST 'http://127.0.0.1:8000/api/shop/customers/login' \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","password":"pass"}'✅ Invalid Payload
# Validate JSON before sending
echo '{"email":"[email protected]","password":"pass"}' | jq .
# Check for missing required fields
curl -X POST 'http://127.0.0.1:8000/api/shop/customers' \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]"}' # Missing password✅ Rate Limiting
# Check rate limit headers
curl -i -X GET 'http://127.0.0.1:8000/api/shop/products' \
-H 'Accept: application/json'
# Response headers:
# X-RateLimit-Limit: 1000
# X-RateLimit-Remaining: 999
# X-RateLimit-Reset: 1702000000
# If limit exceeded: wait until Reset time✅ Timeout Issues
# Increase timeout for slow requests
curl --max-time 30 -X GET 'http://127.0.0.1:8000/api/shop/products?itemsPerPage=1000'
# Node.js timeout
fetch(url, { signal: AbortSignal.timeout(5000) })Common Error Responses
401 Unauthorized
{
"@context": "/api/contexts/Error",
"@type": "Error",
"hydra:title": "Unauthorized",
"hydra:description": "Invalid token or missing Authorization header"
}Solution: Check token validity, refresh if expired, re-authenticate
403 Forbidden
{
"@context": "/api/contexts/Error",
"@type": "Error",
"hydra:title": "Forbidden",
"hydra:description": "Access denied to this resource"
}Solution: User doesn't have permission, check roles and ACL
404 Not Found
{
"@context": "/api/contexts/Error",
"@type": "Error",
"hydra:title": "Not Found",
"hydra:description": "Resource not found"
}Solution: Verify endpoint path and resource ID exist
422 Unprocessable Entity
{
"@context": "/api/contexts/ConstraintViolationList",
"@type": "ConstraintViolationList",
"hydra:title": "Validation Failed",
"violations": [
{
"propertyPath": "email",
"message": "This value is not a valid email address."
}
]
}Solution: Check request payload validation, ensure required fields are present and valid
429 Too Many Requests
{
"@context": "/api/contexts/Error",
"@type": "Error",
"hydra:title": "Rate Limit Exceeded",
"hydra:description": "Too many requests. Try again later."
}Solution: Wait for rate limit reset, implement exponential backoff
REST vs GraphQL Testing
When to Use REST APIs
- ✅ Simple CRUD operations (Create, Read, Update, Delete)
- ✅ Fetching single resources by ID
- ✅ Standard HTTP operations
- ✅ File uploads/downloads
- ✅ Mobile apps with limited bandwidth
When to Use GraphQL
- ✅ Complex nested data queries
- ✅ Multiple resources in single request
- ✅ Client-defined response structure
- ✅ Real-time subscriptions
- ✅ Reducing over-fetching
Testing both:
# REST - Get single locale
curl -X GET 'http://127.0.0.1:8000/api/shop/locales/1'
# GraphQL - Query with flexibility
curl -X POST 'http://127.0.0.1:8000/graphql' \
-H 'Content-Type: application/json' \
-d '{"query":"{ locale(id:1) { id code name direction } }"}'Monitoring API Performance
Response Time Tracking
# Measure endpoint response time
time curl -s -X GET 'http://127.0.0.1:8000/api/shop/products?page=1' \
-H 'Accept: application/json' | jq . > /dev/null
# Output: real 0m0.234s (234ms)Load Testing with Apache Bench
# Install: apt-get install apache2-utils
# Test endpoint with 100 requests, 10 concurrent
ab -n 100 -c 10 'http://127.0.0.1:8000/api/shop/products'Load Testing with wrk
# Install: apt-get install wrk or brew install wrk
# Test with 4 threads, 100 connections, 30 second duration
wrk -t4 -c100 -d30s 'http://127.0.0.1:8000/api/shop/products'Automated Testing with Jest
describe('REST API - Locales', () => {
const baseURL = 'http://127.0.0.1:8000';
test('GET single locale', async () => {
const response = await fetch(`${baseURL}/api/shop/locales/1`);
expect(response.status).toBe(200);
const data = await response.json();
expect(data.id).toBe(1);
expect(data).toHaveProperty('code');
expect(data).toHaveProperty('name');
});
test('Invalid locale ID returns 404', async () => {
const response = await fetch(`${baseURL}/api/shop/locales/9999`);
expect(response.status).toBe(404);
});
});API Documentation Schema
Access the OpenAPI schema for automated tools:
http://your-domain.com/api/docs.jsonThis JSON schema can be used with:
- Swagger/OpenAPI tools
- API code generators
- Documentation generators
- API testing frameworks

