Fetch Statements Reporting
curl --request GET \
--url https://api.qobra.co/v2/reporting/{table_id}/statements \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.qobra.co/v2/reporting/{table_id}/statements"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.qobra.co/v2/reporting/{table_id}/statements', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.qobra.co/v2/reporting/{table_id}/statements",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.qobra.co/v2/reporting/{table_id}/statements"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.qobra.co/v2/reporting/{table_id}/statements")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.qobra.co/v2/reporting/{table_id}/statements")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": [
{
"standard.id": "65a1b2c3d4e5f6g7h8i9j0k1",
"standard.user": {
"id": "507f191e810c19729de860ea",
"email": "sarah.johnson@company.com"
},
"standard.date": "2024-01-01",
"standard.total_commission": {
"value": 8500,
"currency": "USD"
},
"standard.status": "paid",
"custom.quota_attainment": 0.92,
"custom.tier": "Accelerator"
},
{
"standard.id": "65a1b2c3d4e5f6g7h8i9j0k2",
"standard.user": {
"id": "507f191e810c19729de860eb",
"email": "michael.chen@company.com"
},
"standard.date": "2024-01-01",
"standard.total_commission": {
"value": 12750,
"currency": "USD"
},
"standard.status": "validated",
"custom.quota_attainment": 1.15,
"custom.tier": "Overachievement"
}
],
"meta": {
"next_start_id": "65a1b2c3d4e5f6g7h8i9j999",
"has_more": true,
"next_url": "https://api.qobra.co/v2/reporting/507f1f77bcf86cd799439011/statements?start_id=65a1b2c3d4e5f6g7h8i9j999&limit=1000"
}
}{
"count": 1,
"errors": [
{
"error": "ValidationError",
"resource": "start_id",
"description": "Can't parse value for param 'start_id' : Value error, Invalid ObjectId"
}
]
}{
"message": "You're trying to access resource you're not authorized to.",
"type": "UnauthorizedError"
}{
"message": "We couldn't find the requested resource",
"resource": "ObjectModel",
"type": "NotFoundError"
}Reporting
Fetch Statements Reporting
Extracts commission statement records from a statement reporting data structure. Statements represent the final calculated commissions—what each person earned in each period. Use this endpoint for payroll integration, commission reports, earnings history analysis, and compliance audit trails.
GET
/
v2
/
reporting
/
{table_id}
/
statements
Fetch Statements Reporting
curl --request GET \
--url https://api.qobra.co/v2/reporting/{table_id}/statements \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.qobra.co/v2/reporting/{table_id}/statements"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.qobra.co/v2/reporting/{table_id}/statements', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.qobra.co/v2/reporting/{table_id}/statements",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.qobra.co/v2/reporting/{table_id}/statements"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.qobra.co/v2/reporting/{table_id}/statements")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.qobra.co/v2/reporting/{table_id}/statements")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": [
{
"standard.id": "65a1b2c3d4e5f6g7h8i9j0k1",
"standard.user": {
"id": "507f191e810c19729de860ea",
"email": "sarah.johnson@company.com"
},
"standard.date": "2024-01-01",
"standard.total_commission": {
"value": 8500,
"currency": "USD"
},
"standard.status": "paid",
"custom.quota_attainment": 0.92,
"custom.tier": "Accelerator"
},
{
"standard.id": "65a1b2c3d4e5f6g7h8i9j0k2",
"standard.user": {
"id": "507f191e810c19729de860eb",
"email": "michael.chen@company.com"
},
"standard.date": "2024-01-01",
"standard.total_commission": {
"value": 12750,
"currency": "USD"
},
"standard.status": "validated",
"custom.quota_attainment": 1.15,
"custom.tier": "Overachievement"
}
],
"meta": {
"next_start_id": "65a1b2c3d4e5f6g7h8i9j999",
"has_more": true,
"next_url": "https://api.qobra.co/v2/reporting/507f1f77bcf86cd799439011/statements?start_id=65a1b2c3d4e5f6g7h8i9j999&limit=1000"
}
}{
"count": 1,
"errors": [
{
"error": "ValidationError",
"resource": "start_id",
"description": "Can't parse value for param 'start_id' : Value error, Invalid ObjectId"
}
]
}{
"message": "You're trying to access resource you're not authorized to.",
"type": "UnauthorizedError"
}{
"message": "We couldn't find the requested resource",
"resource": "ObjectModel",
"type": "NotFoundError"
}Overview
This endpoint extracts commission statement records from a statement reporting data structure. Statements represent the final calculated commissions — what each person earned in each period. Use this endpoint for:- Payroll integration (sending commissions to payroll systems)
- Commission reports and dashboards
- Earnings history analysis
- Compliance and audit trails
Statements = Results. This endpoint gives you the output of Qobra’s
commission calculations, not the underlying deals/activities.
Only reporting tables from your company’s live environment are reachable.
A
table_id that belongs to a sandbox environment returns 404 Not Found,
even if the id was copied from the Qobra app while viewing a sandbox.Pagination
This endpoint uses ID-based pagination for consistent performance with large datasets.Basic Pagination Pattern
url = f"https://api.qobra.co/v2/reporting/{table_id}/statements"
params = {"limit": 2000}
while True:
response = requests.get(url, headers=headers, params=params)
result = response.json()
# Process records
for record in result["data"]:
process(record)
# Check if more pages exist
if not result["meta"]["has_more"]:
break
# Use next_url for next page
url = result["meta"]["next_url"]
Use
next_url for simplicity: The API returns a pre-constructed
next_url in the response meta—just follow it instead of manually building
the next request.Filtering by modification date
Uselast_modified_after to implement incremental sync (only fetch new/updated records).
Incremental sync pattern
from datetime import datetime, timezone
def incremental_sync(table_id: str, api_key: str):
# Load last sync time from your database
last_sync = get_last_sync_time() # e.g., 2024-01-14T00:00:00Z
url = f"https://api.qobra.co/v2/reporting/{table_id}/statements"
headers = {"X-API-Key": api_key}
params = {
"limit": 2000,
"last_modified_after": last_sync.isoformat()
}
new_records = []
while True:
response = requests.get(url, headers=headers, params=params)
result = response.json()
new_records.extend(result["data"])
if not result["meta"]["has_more"]:
break
url = result["meta"]["next_url"]
# Save current time as last sync
save_last_sync_time(datetime.now(timezone.utc))
return new_records
# Usage: Daily incremental sync
new_statements = incremental_sync(table_id, api_key)
print(f"Found {len(new_statements)} new/updated statements since last sync")
- ✅ 10-100x faster than full extracts
- ✅ Reduces API load
- ✅ Keeps your data warehouse up-to-date with minimal overhead
Performance & best practices
Use ID-based pagination
Always use
next_url for large datasets (10K+).url = result["meta"]["next_url"]
Implement incremental sync
Use
last_modified_after for daily/hourly updates.params = {"last_modified_after": last_sync}
Use Limit 2000
Optimal balance between network overhead and response time.
params = {"limit": 2000}
Authorizations
Your Qobra API key. Generate it from Settings > API Keys in Qobra.
Path Parameters
ID of a statement reporting structure (from /v2/data-structures)
Query Parameters
Start after this record ID (for ID-based pagination, recommended)
Number of records per page (1-2000)
Required range:
1 <= x <= 2000ISO 8601 datetime - Only return records modified after this date (for incremental sync)
ISO 8601 datetime - Only return records modified before this date
Was this page helpful?