Usage History
The POST /account/history endpoint returns a paginated list of your BBRE
(Browser-Backed Request Engine) task history, including every request and session operation
that has been processed through your account. This endpoint is essential for understanding
how your BBRE credit is being consumed, identifying failed requests that need attention,
tracking processing times across different configurations, and building internal reporting
dashboards. Every task recorded in your history includes its unique identifier, the type
of operation (standard request or session request), the operating mode used (passive or
adaptive), the final status (completed, failed, processing, or timeout), the target URL,
the HTTP method, the exact price charged for that operation, the processing time in
milliseconds, and timestamps for both creation and completion. The endpoint supports
powerful filtering capabilities that let you narrow results by task status, date range,
or both. Combined with pagination through the limit and offset
parameters, you can efficiently retrieve and analyze any subset of your usage data
regardless of how many total tasks your account has processed. Results are always returned
in reverse chronological order (newest first), which means the most recent operations
appear at the top of the list. This ordering is fixed and cannot be changed through
request parameters. Whether you are debugging a specific failed request, calculating your
daily spend, analyzing success rates across different target domains, or exporting your
complete usage data for external analysis, this endpoint provides the raw data you need.
This page covers the endpoint definition, authentication requirements, all available
request parameters, the complete response format, filtering examples, pagination patterns,
working code examples in JavaScript, Python, and cURL, data analysis patterns, error
handling, and best practices for working with usage history data in production systems.
Your usage history contains every task that has been submitted through your API key, including tasks that are still processing, tasks that completed successfully, tasks that failed, and tasks that timed out. Each history entry records the exact cost charged for that operation, so you can use this data to reconcile your balance changes and understand your spending patterns. The history is ordered by creation time (newest first) and supports filtering by status and date range. For large accounts with thousands of tasks, use the pagination parameters to retrieve data in manageable chunks rather than requesting everything at once. The default page size is 50 tasks, which provides a good balance between response size and the number of API calls needed to iterate through your data.
Endpoint
The usage history endpoint accepts only POST requests. Unlike the balance endpoint which supports both GET and POST, the history endpoint requires POST because it accepts an optional JSON request body containing filter and pagination parameters. Even if you do not need any filters, you must send a POST request. You can send an empty body or an empty JSON object, and the endpoint will return the first 50 tasks ordered by creation date (newest first) with no filters applied.
Authentication
All requests to the BBRE API require authentication via an API key. You must include your
API key in the HTTP headers of every request, including history queries. The API accepts
the key through either the x-api-key header or the apikey
header. Both header names are supported and functionally identical. If no API key is
provided, the API returns a 401 error with the API_KEY_REQUIRED
error code. If the provided key is invalid or belongs to a suspended or inactive account,
the API returns a 403 error with the appropriate error code
(INVALID_API_KEY, ACCOUNT_SUSPENDED, or
ACCOUNT_INACTIVE).
| Header | Type | Required | Description |
|---|---|---|---|
x-api-key |
string | required | Your BBRE API key. You can find this in your MyDisct Solver dashboard. |
Content-Type |
string | optional | Set to application/json when sending a JSON request body with filter or pagination parameters. |
When sending filter or pagination parameters in the request body, include the
Content-Type: application/json header so the server can parse your JSON
payload correctly. If you are sending an empty request with no filters, the Content-Type
header is not strictly required, but including it is a good practice for consistency
across all your BBRE API calls.
Request Parameters
All parameters for the usage history endpoint are optional. If you send an empty request body or omit all parameters, the endpoint returns the most recent 50 tasks with no filters applied. The parameters allow you to control pagination (how many results to return and where to start) and filtering (which tasks to include based on status or date range). All parameters are sent in the JSON request body.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit |
number | optional | Maximum number of tasks to return per page. Defaults to 50 if not specified. Use this to control the response size. Smaller values mean faster responses and less memory usage on the client side, while larger values reduce the number of API calls needed to iterate through your complete history. |
offset |
number | optional | Number of tasks to skip before starting to return results. Defaults to 0 (start from the beginning). Use this in combination with limit to implement pagination. For example, to get the second page of 50 results, set offset to 50. |
status |
string | optional | Filter tasks by their current status. Accepted values are "completed", "failed", "processing", and "timeout". When specified, only tasks matching the given status are returned. The pagination counts (total, limit, offset) reflect the filtered result set, not the total number of tasks in your account. |
startDate |
string | optional | ISO 8601 date string. When specified, only tasks created on or after this date are returned. Use this to limit results to a specific time window. Example: "2024-06-01T00:00:00.000Z" returns tasks from June 1, 2024 onwards. |
endDate |
string | optional | ISO 8601 date string. When specified, only tasks created on or before this date are returned. Use this together with startDate to define a specific date range. Example: "2024-06-30T23:59:59.999Z" returns tasks up to the end of June 30, 2024. |
You can combine all filter parameters in a single request. For example, you can filter by
status and date range simultaneously to find all failed tasks within a specific week. The
filters are applied with AND logic, meaning a task must match all specified criteria to be
included in the results. The pagination parameters (limit and
offset) are applied after filtering, so the total count in the
response reflects the number of tasks that match your filters, not the total number of
tasks in your account.
Response Format
The history endpoint returns a JSON response containing an array of task objects and
pagination metadata. On success, the response includes the standard BBRE success fields,
a tasks array with detailed information about each task, and a
pagination object that tells you the total number of matching tasks, the
current limit, and the current offset. This pagination metadata is essential for
implementing page navigation in your application.
Success Response (200)
A successful history query returns the following structure. The tasks array
contains task objects ordered by creation date (newest first). Each task object includes
all the information you need to understand what happened with that specific operation:
what was requested, how it was processed, how long it took, and how much it cost. The
pagination object provides the metadata needed to navigate through large
result sets.
{
"success": true,
"service": "MyDisct Solver BBRE",
"tasks": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "BBRE_REQUEST",
"mode": "passive",
"status": "completed",
"url": "https://example.com/api/data",
"method": "GET",
"priceCharged": 0.005,
"processingTime": 1234,
"createdAt": "2024-06-15T10:30:00.000Z",
"completedAt": "2024-06-15T10:30:01.234Z"
},
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"type": "BBRE_SESSION_REQUEST",
"mode": "adaptive",
"status": "completed",
"url": "https://example.com/login",
"method": "POST",
"priceCharged": 0.012,
"processingTime": 3456,
"createdAt": "2024-06-15T10:28:00.000Z",
"completedAt": "2024-06-15T10:28:03.456Z"
}
],
"pagination": {
"total": 15420,
"limit": 50,
"offset": 0
}
}
Tasks Array Fields
Each object in the tasks array represents a single BBRE operation that was
processed through your account. The fields provide complete visibility into what was
requested, how it was handled, and the outcome.
| Field | Type | Description |
|---|---|---|
id |
string | Unique identifier (UUID) for this task. Use this ID to reference a specific task when debugging or when querying the result endpoint for completed tasks. |
type |
string | The type of BBRE operation. "BBRE_REQUEST" indicates a standard request created through the request API. "BBRE_SESSION_REQUEST" indicates a request made within an active session. |
mode |
string | The operating mode used for this task. Either "passive" (simple HTTP request mode) or "adaptive" (full browser automation mode). Adaptive mode tasks typically have higher processing times and costs. |
status |
string | The current status of the task. Possible values: "processing" (task is still being executed), "completed" (task finished successfully), "failed" (task encountered an error), "timeout" (task exceeded the maximum processing time). |
url |
string | The target URL that was requested. This is the URL you provided when creating the task or sending the session request. |
method |
string | The HTTP method used for the request (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS). |
priceCharged |
number | The amount charged for this task in USD. This is the exact amount that was deducted from your account balance when the task completed. Failed tasks and timed-out tasks may still have a charge depending on how far processing progressed before the failure. |
processingTime |
number | The total processing time for this task in milliseconds. This measures the time from when the BBRE engine started processing the task to when it completed, failed, or timed out. Does not include queue wait time. |
createdAt |
string | ISO 8601 timestamp indicating when the task was created (submitted to the API). Tasks are ordered by this field in descending order (newest first). |
completedAt |
string | ISO 8601 timestamp indicating when the task finished processing. This field is present for completed, failed, and timed-out tasks. For tasks still in "processing" status, this field may be null. |
Pagination Object
The pagination object provides metadata about the result set, which you need
to implement page navigation and to know when you have retrieved all matching tasks.
| Field | Type | Description |
|---|---|---|
total |
number | The total number of tasks matching your filter criteria. If no filters are applied, this is the total number of tasks in your account. Use this value to calculate the total number of pages and to determine when you have retrieved all results. |
limit |
number | The maximum number of tasks returned in this response. This reflects the limit parameter you sent in the request, or the default value of 50 if you did not specify one. |
offset |
number | The number of tasks skipped before the current result set. This reflects the offset parameter you sent in the request, or 0 if you did not specify one. To get the next page, add the current limit to the current offset. |
Error Response Examples
When the history query fails, the API returns an error response with the appropriate HTTP status code, error code, and a descriptive message. The most common error scenarios for this endpoint are authentication-related, since the filter parameters are all optional and the endpoint handles invalid values gracefully.
401 - API Key Required
{
"success": false,
"service": "MyDisct Solver BBRE",
"error": {
"code": "API_KEY_REQUIRED",
"message": "API key is required. Please provide your API key in the x-api-key or apikey header."
}
}
403 - Invalid API Key
{
"success": false,
"service": "MyDisct Solver BBRE",
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or does not exist."
}
}
403 - Account Suspended
{
"success": false,
"service": "MyDisct Solver BBRE",
"error": {
"code": "ACCOUNT_SUSPENDED",
"message": "Your account has been suspended. Please contact support for more information."
}
}
500 - Service Error
{
"success": false,
"service": "MyDisct Solver BBRE",
"error": {
"code": "SERVICE_ERROR",
"message": "An internal server error occurred. Please try again later."
}
}
Filtering Examples
The usage history endpoint supports three types of filters that can be used individually or combined: status filtering, date range filtering, and combined filtering. When multiple filters are specified, they are applied with AND logic, meaning a task must satisfy all filter conditions to appear in the results. The following examples demonstrate each filtering approach with complete request and response structures.
Filter by Status
Filtering by status is the most common use case. You might want to find all failed tasks
to investigate errors, all completed tasks to calculate success metrics, or all timed-out
tasks to identify URLs that consistently exceed the processing time limit. The
status parameter accepts a single status value as a string.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getFailedTasks() {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
status: "failed",
limit: 20
})
});
const data = await response.json();
if (data.success) {
console.log("Total failed tasks: " + data.pagination.total);
for (const task of data.tasks) {
console.log(task.id + " | " + task.url + " | " + task.mode);
}
}
return data;
}
getFailedTasks();
The four valid status values are "completed" for tasks that finished
successfully, "failed" for tasks that encountered an error during processing,
"processing" for tasks that are currently being executed by the BBRE engine,
and "timeout" for tasks that exceeded the maximum allowed processing time.
Filtering by "processing" status is useful for monitoring active workloads
and detecting tasks that may be stuck.
Filter by Date Range
Date range filtering lets you retrieve tasks from a specific time period. This is
essential for generating daily, weekly, or monthly usage reports. Both
startDate and endDate accept ISO 8601 formatted date strings.
You can use either or both parameters: specifying only startDate returns all
tasks from that date forward, specifying only endDate returns all tasks up
to that date, and specifying both creates a bounded time window.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getTasksForDateRange(startDate, endDate) {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
startDate: startDate,
endDate: endDate,
limit: 100
})
});
const data = await response.json();
if (data.success) {
console.log("Tasks in range: " + data.pagination.total);
console.log("Returned: " + data.tasks.length);
}
return data;
}
getTasksForDateRange("2024-06-01T00:00:00.000Z", "2024-06-30T23:59:59.999Z");
Combined Filters
Combining status and date range filters gives you precise control over which tasks are returned. For example, you can find all failed tasks from the past week, all completed tasks from a specific day, or all timed-out tasks from the last month. This is particularly useful for incident investigation when you need to understand what went wrong during a specific time period.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getFailedTasksThisWeek() {
const now = new Date();
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
status: "failed",
startDate: weekAgo.toISOString(),
endDate: now.toISOString(),
limit: 100
})
});
const data = await response.json();
if (data.success) {
console.log("Failed tasks this week: " + data.pagination.total);
const totalCost = data.tasks.reduce((sum, task) => sum + task.priceCharged, 0);
console.log("Total cost of failed tasks: $" + totalCost.toFixed(4));
}
return data;
}
getFailedTasksThisWeek();
Pagination Patterns
When your account has more tasks than can fit in a single response, you need to paginate
through the results using the limit and offset parameters. The
pagination.total field in the response tells you the total number of matching
tasks, and you can calculate the number of pages by dividing the total by your limit value.
The following patterns demonstrate how to iterate through all results efficiently.
Iterating Through All Results
The most common pagination pattern is to start at offset 0 and increment the offset by the limit value after each request until you have retrieved all tasks. The loop terminates when the current offset plus the number of returned tasks equals or exceeds the total count. This approach works well for data export, reporting, and analysis workflows where you need to process every task in your history.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getAllTasks(filters) {
const allTasks = [];
const pageSize = 100;
let offset = 0;
let total = null;
while (true) {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
...filters,
limit: pageSize,
offset: offset
})
});
const data = await response.json();
if (!data.success) {
throw new Error("API error: " + data.error.code);
}
allTasks.push(...data.tasks);
total = data.pagination.total;
console.log("Fetched " + allTasks.length + " of " + total + " tasks");
if (allTasks.length >= total) {
break;
}
offset += pageSize;
}
return allTasks;
}
getAllTasks({ status: "completed" }).then(tasks => {
console.log("Total completed tasks: " + tasks.length);
});
Page-Based Navigation
If you are building a user interface that displays history data with page numbers, you can calculate the offset from the page number and page size. This pattern is useful for web dashboards and admin panels where users navigate between pages of results.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getPage(pageNumber, pageSize) {
const offset = (pageNumber - 1) * pageSize;
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
limit: pageSize,
offset: offset
})
});
const data = await response.json();
if (data.success) {
const totalPages = Math.ceil(data.pagination.total / pageSize);
console.log("Page " + pageNumber + " of " + totalPages);
console.log("Showing " + data.tasks.length + " tasks");
console.log("Total tasks: " + data.pagination.total);
}
return data;
}
getPage(1, 25);
getPage(3, 25);
Python Pagination
A Python implementation of the full iteration pattern. This is useful when you need to export your complete usage history for analysis in tools like pandas, Excel, or a custom reporting system.
import requests
API_BASE = "https://bbre-solver-api.mydisct.com"
API_KEY = "YOUR_API_KEY"
headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY
}
def get_all_tasks(status_filter=None, page_size=100):
all_tasks = []
offset = 0
while True:
payload = {
"limit": page_size,
"offset": offset
}
if status_filter:
payload["status"] = status_filter
response = requests.post(
API_BASE + "/account/history",
headers=headers,
json=payload
)
data = response.json()
if not data["success"]:
raise Exception(f"API error: {data['error']['code']}")
all_tasks.extend(data["tasks"])
total = data["pagination"]["total"]
print(f"Fetched {len(all_tasks)} of {total} tasks")
if len(all_tasks) >= total:
break
offset += page_size
return all_tasks
tasks = get_all_tasks(status_filter="completed")
print(f"Total completed tasks: {len(tasks)}")
Code Examples
The following examples demonstrate how to query your usage history using different
programming languages. All examples show complete, working code that you can copy and
run directly. Remember to replace YOUR_API_KEY with your actual BBRE API
key. Each example includes filter parameters to demonstrate the full request format.
JavaScript (fetch)
A complete JavaScript example using the native fetch API to retrieve usage
history with status filtering and pagination. This example fetches the most recent 10
completed tasks and displays their details.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getUsageHistory() {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
status: "completed",
limit: 10,
offset: 0
})
});
const data = await response.json();
if (data.success) {
console.log("Total completed tasks: " + data.pagination.total);
console.log("Showing: " + data.tasks.length);
for (const task of data.tasks) {
const cost = "$" + task.priceCharged.toFixed(4);
const time = task.processingTime + "ms";
console.log(task.id + " | " + task.url + " | " + cost + " | " + time);
}
} else {
console.log("Error: " + data.error.code + " - " + data.error.message);
}
return data;
}
getUsageHistory();
JavaScript with Date Range Filter
This example demonstrates how to query tasks within a specific date range. It retrieves all tasks from the current month and calculates the total spending for that period.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getMonthlyHistory() {
const now = new Date();
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
startDate: firstDayOfMonth.toISOString(),
endDate: now.toISOString(),
limit: 100
})
});
const data = await response.json();
if (data.success) {
const totalSpent = data.tasks.reduce((sum, t) => sum + t.priceCharged, 0);
console.log("Tasks this month: " + data.pagination.total);
console.log("Total spent (this page): $" + totalSpent.toFixed(4));
}
return data;
}
getMonthlyHistory();
Python (requests library)
A Python example using the requests library to query usage history with
combined filters. This example retrieves failed tasks from the past 7 days and prints
a summary of each failure.
import requests
from datetime import datetime, timedelta
API_BASE = "https://bbre-solver-api.mydisct.com"
API_KEY = "YOUR_API_KEY"
headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY
}
now = datetime.utcnow()
week_ago = now - timedelta(days=7)
payload = {
"status": "failed",
"startDate": week_ago.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
"endDate": now.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
"limit": 50,
"offset": 0
}
response = requests.post(
API_BASE + "/account/history",
headers=headers,
json=payload
)
data = response.json()
if data["success"]:
print(f"Failed tasks (last 7 days): {data['pagination']['total']}")
for task in data["tasks"]:
print(f" {task['id']} | {task['url']} | {task['mode']} | ${task['priceCharged']:.4f}")
else:
print(f"Error: {data['error']['code']}")
Python with Full Pagination
A more complete Python example that iterates through all pages of results and collects every task matching the filter criteria. This is useful for data export and analysis workflows.
import requests
API_BASE = "https://bbre-solver-api.mydisct.com"
API_KEY = "YOUR_API_KEY"
headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY
}
def fetch_all_history(status_filter=None):
all_tasks = []
offset = 0
page_size = 100
while True:
payload = {"limit": page_size, "offset": offset}
if status_filter:
payload["status"] = status_filter
response = requests.post(
API_BASE + "/account/history",
headers=headers,
json=payload
)
data = response.json()
if not data["success"]:
print(f"Error: {data['error']['code']}")
break
all_tasks.extend(data["tasks"])
total = data["pagination"]["total"]
if len(all_tasks) >= total:
break
offset += page_size
return all_tasks
completed_tasks = fetch_all_history("completed")
total_cost = sum(t["priceCharged"] for t in completed_tasks)
print(f"All completed tasks: {len(completed_tasks)}")
print(f"Total cost: ${total_cost:.4f}")
cURL
Quick history queries from the command line using cURL. These examples demonstrate different filter combinations that you can use for quick checks and debugging.
curl -X POST https://bbre-solver-api.mydisct.com/account/history \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"limit": 10}'
curl -X POST https://bbre-solver-api.mydisct.com/account/history \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"status": "failed", "limit": 20}'
curl -X POST https://bbre-solver-api.mydisct.com/account/history \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"status": "completed", "startDate": "2024-06-01T00:00:00.000Z", "endDate": "2024-06-30T23:59:59.999Z", "limit": 50}'
Data Analysis Patterns
The usage history data contains rich information that you can analyze to optimize your BBRE usage, reduce costs, and improve reliability. The following patterns demonstrate common analysis workflows that extract actionable insights from your task history.
Cost Tracking and Spending Analysis
Track your spending over time by aggregating the priceCharged field across
tasks. This pattern calculates daily spending totals and identifies which types of
operations consume the most credit. Understanding your cost distribution helps you
optimize your configuration choices and budget allocation.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function analyzeCosts(startDate, endDate) {
const allTasks = [];
let offset = 0;
while (true) {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
startDate: startDate,
endDate: endDate,
limit: 100,
offset: offset
})
});
const data = await response.json();
allTasks.push(...data.tasks);
if (allTasks.length >= data.pagination.total) break;
offset += 100;
}
const totalCost = allTasks.reduce((sum, t) => sum + t.priceCharged, 0);
const avgCost = totalCost / allTasks.length;
const costByMode = {};
for (const task of allTasks) {
if (!costByMode[task.mode]) costByMode[task.mode] = 0;
costByMode[task.mode] += task.priceCharged;
}
const costByType = {};
for (const task of allTasks) {
if (!costByType[task.type]) costByType[task.type] = 0;
costByType[task.type] += task.priceCharged;
}
console.log("Total tasks: " + allTasks.length);
console.log("Total cost: $" + totalCost.toFixed(4));
console.log("Average cost per task: $" + avgCost.toFixed(4));
console.log("Cost by mode:", costByMode);
console.log("Cost by type:", costByType);
return { totalCost, avgCost, costByMode, costByType };
}
analyzeCosts("2024-06-01T00:00:00.000Z", "2024-06-30T23:59:59.999Z");
Failure Analysis
Analyzing failed tasks helps you identify problematic URLs, configurations, or patterns that consistently cause failures. This pattern groups failed tasks by URL domain and mode to reveal which combinations are unreliable, allowing you to adjust your approach for those specific targets.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function analyzeFailures() {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
status: "failed",
limit: 100
})
});
const data = await response.json();
if (!data.success) {
console.log("Error: " + data.error.code);
return;
}
const failuresByDomain = {};
for (const task of data.tasks) {
const url = new URL(task.url);
const domain = url.hostname;
if (!failuresByDomain[domain]) {
failuresByDomain[domain] = { count: 0, modes: {} };
}
failuresByDomain[domain].count++;
if (!failuresByDomain[domain].modes[task.mode]) {
failuresByDomain[domain].modes[task.mode] = 0;
}
failuresByDomain[domain].modes[task.mode]++;
}
console.log("Total failed tasks: " + data.pagination.total);
console.log("Failures by domain:");
for (const [domain, info] of Object.entries(failuresByDomain)) {
console.log(" " + domain + ": " + info.count + " failures");
for (const [mode, count] of Object.entries(info.modes)) {
console.log(" " + mode + ": " + count);
}
}
}
analyzeFailures();
Performance Monitoring with Python
Track processing times across your tasks to identify performance trends and outliers. This Python example calculates average processing times grouped by mode and identifies tasks that took significantly longer than average, which may indicate targets that need different configuration settings.
import requests
API_BASE = "https://bbre-solver-api.mydisct.com"
API_KEY = "YOUR_API_KEY"
headers = {
"Content-Type": "application/json",
"x-api-key": API_KEY
}
response = requests.post(
API_BASE + "/account/history",
headers=headers,
json={"status": "completed", "limit": 100}
)
data = response.json()
if data["success"]:
tasks = data["tasks"]
by_mode = {}
for task in tasks:
mode = task["mode"]
if mode not in by_mode:
by_mode[mode] = []
by_mode[mode].append(task["processingTime"])
for mode, times in by_mode.items():
avg_time = sum(times) / len(times)
max_time = max(times)
min_time = min(times)
print(f"Mode: {mode}")
print(f" Tasks: {len(times)}")
print(f" Avg processing time: {avg_time:.0f}ms")
print(f" Min: {min_time}ms | Max: {max_time}ms")
total_cost = sum(t["priceCharged"] for t in tasks)
success_rate = len(tasks) / data["pagination"]["total"] * 100
print(f"Total cost (this page): ${total_cost:.4f}")
print(f"Tasks shown: {len(tasks)} of {data['pagination']['total']}")
Daily Usage Summary
Generate a daily summary of your BBRE usage by grouping tasks by date. This pattern is useful for building internal dashboards that track daily request volumes, success rates, and spending trends over time.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getDailySummary(startDate, endDate) {
const allTasks = [];
let offset = 0;
while (true) {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({
startDate: startDate,
endDate: endDate,
limit: 100,
offset: offset
})
});
const data = await response.json();
allTasks.push(...data.tasks);
if (allTasks.length >= data.pagination.total) break;
offset += 100;
}
const dailyStats = {};
for (const task of allTasks) {
const day = task.createdAt.split("T")[0];
if (!dailyStats[day]) {
dailyStats[day] = { total: 0, completed: 0, failed: 0, cost: 0 };
}
dailyStats[day].total++;
dailyStats[day][task.status]++;
dailyStats[day].cost += task.priceCharged;
}
console.log("Daily Usage Summary:");
for (const [day, stats] of Object.entries(dailyStats).sort()) {
const successRate = stats.total > 0
? ((stats.completed / stats.total) * 100).toFixed(1)
: "0.0";
console.log(day + " | " + stats.total + " tasks | " + successRate + "% success | $" + stats.cost.toFixed(4));
}
return dailyStats;
}
getDailySummary("2024-06-01T00:00:00.000Z", "2024-06-07T23:59:59.999Z");
Error Codes
The following table lists all error codes that can be returned by the usage history endpoint, along with their HTTP status codes, descriptions, and recommended solutions. Because the history endpoint has only optional parameters, the most common errors are authentication-related. Implementing proper error handling for these codes ensures your history queries and reporting workflows degrade gracefully when issues occur.
| HTTP Status | Error Code | Description | Solution |
|---|---|---|---|
401 |
API_KEY_REQUIRED |
No API key was provided in the request headers. The history endpoint requires authentication like all other BBRE endpoints. | Include your API key in the x-api-key or apikey header. Verify that your HTTP client is sending the header correctly and that it is not being stripped by a proxy or middleware. |
403 |
INVALID_API_KEY |
The provided API key is not valid or does not exist in the system. | Verify your API key in the MyDisct Solver dashboard. Ensure you are copying the complete key without extra spaces or line breaks. If you recently regenerated your key, update it in your application configuration. |
403 |
ACCOUNT_SUSPENDED |
Your account has been suspended. Suspended accounts cannot access any BBRE API endpoints, including the history endpoint. | Contact MyDisct Solver support for information about your account suspension and steps to resolve it. |
403 |
ACCOUNT_INACTIVE |
Your account is inactive. Inactive accounts need to be activated before they can use the BBRE API. | Activate your account through the MyDisct Solver dashboard or contact support for assistance. |
500 |
SERVICE_ERROR |
An internal server error occurred while processing the history request. This can happen if the database is temporarily overloaded or if there is a connectivity issue between the API server and the database. | Retry the request after a short delay (2-5 seconds). If the error persists, try reducing the limit parameter to request fewer results per page. Contact support if the error continues. |
Error Handling Example
The following example demonstrates robust error handling for the history endpoint. In production systems, your history queries should handle errors gracefully and implement retry logic for transient failures. This is especially important for automated reporting workflows that run on a schedule.
const API_BASE = "https://bbre-solver-api.mydisct.com";
const API_KEY = "YOUR_API_KEY";
async function getHistorySafe(filters, maxRetries) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(API_BASE + "/account/history", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify(filters)
});
const data = await response.json();
if (data.success) {
return { tasks: data.tasks, pagination: data.pagination, error: null };
}
const errorCode = data.error.code;
if (errorCode === "API_KEY_REQUIRED" || errorCode === "INVALID_API_KEY") {
return { tasks: [], pagination: null, error: "Authentication failed: " + errorCode };
}
if (errorCode === "ACCOUNT_SUSPENDED" || errorCode === "ACCOUNT_INACTIVE") {
return { tasks: [], pagination: null, error: "Account issue: " + errorCode };
}
if (errorCode === "SERVICE_ERROR" && attempt < maxRetries) {
const delay = attempt * 2000;
console.log("Service error, retrying in " + delay + "ms...");
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return { tasks: [], pagination: null, error: "API error: " + errorCode };
} catch (networkError) {
if (attempt < maxRetries) {
const delay = attempt * 2000;
console.log("Network error, retrying in " + delay + "ms...");
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return { tasks: [], pagination: null, error: "Network error: " + networkError.message };
}
}
}
async function main() {
const result = await getHistorySafe({ limit: 20 }, 3);
if (result.error) {
console.log("Could not fetch history: " + result.error);
return;
}
console.log("Retrieved " + result.tasks.length + " tasks");
console.log("Total matching: " + result.pagination.total);
}
main();
Best Practices
Never attempt to retrieve your entire task history in a single request. Use the
limit and offset parameters to paginate through results
in manageable chunks. A page size of 50-100 tasks provides a good balance between
response size and the number of API calls needed. For data export workflows, iterate
through all pages using a loop that increments the offset by the limit value after
each request. Check the pagination.total field to know when you have
retrieved all matching tasks. This approach prevents memory issues on the client side
and ensures consistent response times from the API.
When you only need specific types of tasks, always use the status and
date range filters to narrow the result set before pagination. Filtering on the server
side is significantly more efficient than retrieving all tasks and filtering on the
client side. For example, if you need to analyze failed tasks from the past week, use
both the status: "failed" filter and the startDate parameter
rather than fetching all tasks and filtering in your application code. Server-side
filtering reduces network bandwidth, response parsing time, and memory usage.
History queries that scan large datasets can occasionally fail due to temporary database load or network issues. Implement retry logic with exponential backoff for your history queries, especially in automated reporting workflows that run on a schedule. Start with a 2-second delay after the first failure and double the delay for each subsequent retry, up to a maximum of 3 retries. This approach handles transient failures without overwhelming the API with rapid retry attempts. For pagination loops, implement retry logic at the individual page level so that a failure on page 5 does not require restarting from page 1.
If you are syncing usage history data to an external system (database, spreadsheet,
analytics platform), use the startDate parameter to fetch only new tasks
since your last sync. Store the timestamp of the most recent task from each sync
operation and use it as the startDate for the next sync. This incremental
approach is much more efficient than re-fetching your entire history on every sync
cycle. It reduces API calls, network bandwidth, and processing time, especially as
your total task count grows over time.
Set up a regular check for failed and timed-out tasks using the status
filter. A sudden increase in failure rates often indicates a problem with a specific
target website (changed structure, added protection), a configuration issue (wrong
mode or sensibility for the target), or a systemic problem that needs attention.
Catching failures early allows you to adjust your approach before they accumulate
and waste significant credit. Consider building an automated alert that triggers
when the failure rate exceeds a threshold, such as more than 10% of tasks failing
within a one-hour window.
Common Issues
Issue 1: Empty Tasks Array Despite Having History
You call the history endpoint and receive a successful response with
"tasks": [] and "total": 0, even though you know your
account has processed tasks. The response structure is correct but contains no data.
Solution: This usually happens when your filter parameters are too
restrictive. Check the following: if you are using the status filter, verify
that the value is one of the four valid statuses ("completed",
"failed", "processing", "timeout") and that it is
spelled correctly with the exact casing shown. If you are using date range filters, verify
that the startDate is before the endDate and that the date
range actually contains tasks. Also check that your dates are in ISO 8601 format. Try
removing all filters first to confirm that your account has history data, then add filters
back one at a time to identify which filter is causing the empty result.
Issue 2: Pagination Returns Duplicate Tasks
When paginating through results, you notice that some tasks appear on multiple pages. Your collected data contains duplicate entries that skew your analysis.
Solution: Duplicates can occur if new tasks are being created while you
are paginating through the results. Because results are ordered by creation date (newest
first), a new task created between your page requests shifts all subsequent tasks by one
position, causing the last task on the previous page to appear as the first task on the
next page. To handle this, deduplicate your collected tasks by the id field
after completing the pagination loop. Alternatively, use the endDate filter
set to the time when you started the pagination to freeze the result set and prevent new
tasks from affecting your pagination.
Issue 3: Total Count Changes Between Pages
The pagination.total value is different on each page of results. Page 1
shows a total of 1500, but page 2 shows a total of 1503, making it difficult to
determine when you have retrieved all tasks.
Solution: The total count reflects the current number of
matching tasks at the time of each request. If new tasks are being created or if tasks
are transitioning between statuses while you paginate, the total will change. This is
expected behavior and not a bug. For accurate pagination, use the total from the first
page as your target and stop when you have collected that many tasks. Alternatively, use
the endDate filter to create a stable snapshot of the data. If the number
of returned tasks on a page is less than the limit, you have reached the
end of the result set regardless of what the total says.
Issue 4: Date Filter Not Working as Expected
You set a startDate and endDate filter, but the results
include tasks outside your expected date range, or the results are empty when you
know tasks exist within that range.
Solution: Ensure your date strings are in ISO 8601 format with the full
timestamp including timezone information. The correct format is
"2024-06-15T00:00:00.000Z" where the Z suffix indicates UTC
timezone. If you omit the time portion or timezone, the server may interpret the date
differently than you expect. Also note that the date filter applies to the
createdAt field of each task, not the completedAt field. A task
created on June 14 that completed on June 15 would be included in a filter for June 14
but not in a filter that starts on June 15. When constructing date ranges for "today",
use the start of the current day in UTC as startDate and the current
timestamp as endDate.