Skip to main content

Mastering API Queries

🎯 Query Like a Pro

Master the art of efficient data retrieval with powerful filtering, pagination, and field selection techniques.

Quick Reference​

🎯 Fields

Select specific columns to optimize response size and speed

?fields=id,name,price
🔍 Filter

Apply conditions to narrow down results

?filter=price>10&active=true
📄 Pagination

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​

ParameterPurposeDefaultRequired
fieldsSpecify which columns to returnAll fields❌
filterApply conditions to filter dataNone❌
pagePage number for pagination1❌
limitMaximum results per page10❌

🎯 Field Selection​

Control exactly what data you receive to optimize performance and reduce bandwidth.

Why Use Field Selection?​

❌ Without Field Selection
  • Downloads all columns (slower)
  • Larger response payloads
  • Higher bandwidth usage
  • Includes unnecessary data
✅ With Field Selection
  • Only downloads what you need
  • Smaller, faster responses
  • Reduced bandwidth costs
  • Cleaner, focused data

Field Selection Examples​

Get only product ID and name
GET /api/v1/inventory/product?fields=id,name
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"

Sample Response:

{
"data": [
{ "id": 1, "name": "Panadol" },
{ "id": 2, "name": "Aspirin" }
],
"meta": { "count": 2, "total": 150 }
}

🔍 Powerful Filtering​

Apply precise conditions to find exactly the data you need.

Filter Operators Reference​

OperatorSyntaxDescriptionExample
Equals=Exact matchname=Panadol
Not Equals!=Exclude exact matchname!=Panadol
Contains*Partial text matchname*pana
Not Contains!*Exclude partial matchname!*generic
Greater Than>Numeric comparisonprice>10
Greater/Equal>=Numeric comparisonprice>=10
Less Than<Numeric comparisonqty<50
Less/Equal<=Numeric comparisonqty<=50
In List[]Match any value in listid[1,2,3]
Not In List![]Exclude values in liststatus![draft,cancel]

Combining Filters​

🔗 AND Logic (&)

All conditions must be true

name*Gel&price>5

Products containing "Gel" AND price greater than 5

🔀 OR Logic (|)

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​

📊 Default Limit

10 records - Perfect for UI lists

⚡ Optimal Range

25-100 records - Balance speed & data

🚨 Large Batches

500+ records - Use with caution

Pagination Examples​

Get second page with 25 items
GET /api/v1/inventory/product?page=2&limit=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​

Complete response anatomy
{
"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
}
}
📊 data

Array of actual records returned by your query. Each object represents one record with the requested fields.

📈 meta
  • count: Records in current response
  • total: Total records matching your filter
📄 pagination

Navigation info for multi-page results. Use nextPage to continue fetching or check totalPages for progress.

Single Record Response​

Single record by ID
{
"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"
}
}
📋 Single vs Multiple Records
  • Multiple records: /inventory/product → Returns array in data with pagination
  • Single record: /inventory/product/123 → Returns object directly in data

🚀 Advanced Query Techniques​

Combining All Parameters​

Advanced inventory analysis query
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
Complex query builder
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);