Mastering API Queries
🎯 Query Like a Pro
Master the art of efficient data retrieval with powerful filtering, pagination, and field selection techniques.
Quick Reference
Select specific columns to optimize response size and speed
?fields=id,name,price
Apply conditions to narrow down results
?filter=price>10&active=true
Navigate through large datasets efficiently
?page=2&limit=50
Understanding GET Requests
GET requests are your primary tool for retrieving data from the Juleb ERP API. They support powerful query parameters that allow you to precisely control what data you receive.
Core Query Parameters
| Parameter | Purpose | Default | Required |
|---|---|---|---|
fields | Specify which columns to return | All fields | ❌ |
filter | Apply conditions to filter data | None | ❌ |
page | Page number for pagination | 1 | ❌ |
limit | Maximum results per page | 10 | ❌ |
🎯 Field Selection
Control exactly what data you receive to optimize performance and reduce bandwidth.
Why Use Field Selection?
- Downloads all columns (slower)
- Larger response payloads
- Higher bandwidth usage
- Includes unnecessary data
- Only downloads what you need
- Smaller, faster responses
- Reduced bandwidth costs
- Cleaner, focused data
Field Selection Examples
- 🔤 Basic Usage
- 🔍 Field Discovery
GET /api/v1/inventory/product?fields=id,name
- cURL
- JavaScript
- Python
curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
"https://$ACCOUNT_NAME.juleb.com/api/v1/inventory/product?fields=id,name"
const response = await fetch(
`https://${accountName}.juleb.com/api/v1/inventory/product?fields=id,name`,
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
}
);
const data = await response.json();
console.log(data);
import requests
response = requests.get(
f'https://{account_name}.juleb.com/api/v1/inventory/product',
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {api_key}'
},
params={'fields': 'id,name'}
)
data = response.json()
print(data)
Sample Response:
{
"data": [
{ "id": 1, "name": "Panadol" },
{ "id": 2, "name": "Aspirin" }
],
"meta": { "count": 2, "total": 150 }
}
Get a quick overview of all available fields by requesting just one record:
GET /api/v1/inventory/product?limit=1
This returns all fields for the first record, helping you identify what data is available.
🔍 Powerful Filtering
Apply precise conditions to find exactly the data you need.
Filter Operators Reference
| Operator | Syntax | Description | Example |
|---|---|---|---|
| Equals | = | Exact match | name=Panadol |
| Not Equals | != | Exclude exact match | name!=Panadol |
| Contains | * | Partial text match | name*pana |
| Not Contains | !* | Exclude partial match | name!*generic |
| Greater Than | > | Numeric comparison | price>10 |
| Greater/Equal | >= | Numeric comparison | price>=10 |
| Less Than | < | Numeric comparison | qty<50 |
| Less/Equal | <= | Numeric comparison | qty<=50 |
| In List | [] | Match any value in list | id[1,2,3] |
| Not In List | ![] | Exclude values in list | status![draft,cancel] |
Combining Filters
All conditions must be true
name*Gel&price>5
Products containing "Gel" AND price greater than 5
At least one condition must be true
categ_id=168|categ_id=169
Products in category 168 OR category 169
📄 Smart Pagination
Efficiently navigate through large datasets without overwhelming your application.
Pagination Strategy
10 records - Perfect for UI lists
25-100 records - Balance speed & data
500+ records - Use with caution
Pagination Examples
- 📋 Basic Pagination
- HTTP Request
- JavaScript
- Python
GET /api/v1/inventory/product?page=2&limit=25
async function fetchProducts(page = 1, limit = 25) {
const response = await fetch(
`https://${accountName}.juleb.com/api/v1/inventory/product?page=${page}&limit=${limit}`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const data = await response.json();
console.log(
`Page ${data.pagination.currentPage} of ${data.pagination.totalPages}`
);
console.log(`Showing ${data.meta.count} of ${data.meta.total} products`);
return data;
}
// Usage
const page2 = await fetchProducts(2, 25);
def get_paginated_products(page=1, limit=25):
response = requests.get(
f'https://{account_name}.juleb.com/api/v1/inventory/product',
headers={'Authorization': f'Bearer {api_key}'},
params={'page': page, 'limit': limit}
)
data = response.json()
print(f"Page {data['pagination']['currentPage']} of {data['pagination']['totalPages']}")
print(f"Showing {data['meta']['count']} of {data['meta']['total']} products")
return data
# Usage
products_page2 = get_paginated_products(2, 25)
Sample Response:
{
"data": [
/* 25 product records */
],
"meta": {
"count": 25,
"total": 1247
},
"pagination": {
"previousPage": 1,
"currentPage": 2,
"nextPage": 3,
"totalPages": 50
}
}
📊 Understanding API Responses
Multi-Record Response Structure
{
"data": [
{
"id": 1,
"name": "Panadol Extra",
"default_code": "MED_1001",
"list_price": 12.5,
"qty_available": 150,
"active": true
},
{
"id": 2,
"name": "Aspirin 325mg",
"default_code": "MED_1002",
"list_price": 8.75,
"qty_available": 89,
"active": true
}
],
"meta": {
"count": 2, // Records in this response
"total": 1247 // Total matching records
},
"pagination": {
"previousPage": 1, // Previous page number (null if first)
"currentPage": 2, // Current page number
"nextPage": 3, // Next page number (null if last)
"totalPages": 624 // Total pages available
}
}
Array of actual records returned by your query. Each object represents one record with the requested fields.
- count: Records in current response
- total: Total records matching your filter
Navigation info for multi-page results. Use nextPage to continue fetching or check totalPages for progress.
Single Record Response
{
"data": {
"id": 1,
"name": "Panadol Extra",
"default_code": "MED_1001",
"list_price": 12.5,
"qty_available": 150,
"active": true,
"categ_id": 168,
"create_date": "2024-01-15T10:30:00Z",
"write_date": "2025-01-28T14:22:00Z"
}
}
- Multiple records:
/inventory/product→ Returns array indatawith pagination - Single record:
/inventory/product/123→ Returns object directly indata
🚀 Advanced Query Techniques
Combining All Parameters
- 🎯 Comprehensive Query
- ⚡ Performance Tips
GET /api/v1/inventory/product?
fields=id,name,default_code,qty_available,list_price,categ_id&
filter=categ_id[168,169,170]&qty_available>0&active=true&list_price>=5&
page=1&
limit=50
class QueryBuilder {
constructor(baseUrl, endpoint) {
this.baseUrl = baseUrl;
this.endpoint = endpoint;
this.params = new URLSearchParams();
}
fields(...fieldNames) {
this.params.set("fields", fieldNames.join(","));
return this;
}
filter(filterString) {
const existing = this.params.get("filter");
if (existing) {
this.params.set("filter", `${existing}&${filterString}`);
} else {
this.params.set("filter", filterString);
}
return this;
}
page(pageNum) {
this.params.set("page", pageNum.toString());
return this;
}
limit(limitNum) {
this.params.set("limit", limitNum.toString());
return this;
}
build() {
return `${this.baseUrl}${this.endpoint}?${this.params.toString()}`;
}
async execute(apiKey) {
const url = this.build();
const response = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
return response.json();
}
}
// Usage example
const query = new QueryBuilder(
`https://${accountName}.juleb.com/api/v1/`,
"inventory/product"
)
.fields("id", "name", "qty_available", "list_price")
.filter("categ_id[168,169]")
.filter("qty_available>10")
.filter("active=true")
.page(1)
.limit(25);
const results = await query.execute(apiKey);
console.log("Advanced query results:", results);
// ✅ GOOD: Specific, filtered query
const efficientQuery = await fetch(
`https://${accountName}.juleb.com/api/v1/inventory/product?` +
`fields=id,name,qty_available&` +
`filter=active=true&qty_available<10&` +
`limit=50`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
// ❌ AVOID: Broad, unfiltered query
const inefficientQuery = await fetch(
`https://${accountName}.juleb.com/api/v1/inventory/product?limit=1000`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
- Always use field selection - Only request the data you need
- Filter early - Apply filters to reduce the dataset size
- Reasonable page sizes - 25-100 records per page is usually optimal
- Cache responses - Store frequently accessed data locally
- Use specific filters - Avoid overly broad queries