curl --request GET \
--url https://api.getbreezyapp.com/v1/reports/job-profitability \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.getbreezyapp.com/v1/reports/job-profitability"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.getbreezyapp.com/v1/reports/job-profitability', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": [
{
"period_start": "2026-08-01",
"period_end": "2026-09-01",
"currency": "USD",
"group": null,
"job_count": 1,
"revenue_cents": 130000,
"labor_cost_cents": 6000,
"parts_cost_cents": 24000,
"equipment_cost_cents": 0,
"misc_cost_cents": 0,
"other_cost_cents": 0,
"total_cost_cents": 30000,
"gross_profit_cents": 100000,
"gross_margin": 0.7692
}
],
"pagination": {
"next_cursor": null
},
"meta": {
"request_id": "11111111-1111-4111-8111-000000009999",
"generated_at": "2026-09-08T19:00:00Z",
"timezone": "America/Los_Angeles"
},
"report": {
"start_date": "2026-08-01",
"end_date": "2026-10-01",
"bucket": "month",
"costing_enabled": true,
"verified_only": true,
"include_excluded_job_types": false,
"group_by": null
}
}{
"error": {
"code": "INVALID_REQUEST",
"message": "end_date must be later than start_date",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "A valid API key is required",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "METHOD_NOT_ALLOWED",
"message": "This resource supports GET",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Request limit exceeded",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "Unable to complete request",
"request_id": "example-request",
"details": []
}
}Summarize recorded job profitability
Enabled costing and TRACKED jobs only; defaults to VERIFIED jobs and included owned job types. Revenue is recorded OPEN/PAID/UNCOLLECTABLE pre-discount, pre-tax invoice subtotals. Whole-job date is earliest qualifying invoice issue time, then work completion, then job creation, in company timezone. One optional business grouping plus time; null business groups retained when eligible. Rows order by period_start then group value, null first. Empty buckets omitted. Margin is calculated from summed amounts, not averaged job margins.
curl --request GET \
--url https://api.getbreezyapp.com/v1/reports/job-profitability \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.getbreezyapp.com/v1/reports/job-profitability"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.getbreezyapp.com/v1/reports/job-profitability', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"data": [
{
"period_start": "2026-08-01",
"period_end": "2026-09-01",
"currency": "USD",
"group": null,
"job_count": 1,
"revenue_cents": 130000,
"labor_cost_cents": 6000,
"parts_cost_cents": 24000,
"equipment_cost_cents": 0,
"misc_cost_cents": 0,
"other_cost_cents": 0,
"total_cost_cents": 30000,
"gross_profit_cents": 100000,
"gross_margin": 0.7692
}
],
"pagination": {
"next_cursor": null
},
"meta": {
"request_id": "11111111-1111-4111-8111-000000009999",
"generated_at": "2026-09-08T19:00:00Z",
"timezone": "America/Los_Angeles"
},
"report": {
"start_date": "2026-08-01",
"end_date": "2026-10-01",
"bucket": "month",
"costing_enabled": true,
"verified_only": true,
"include_excluded_job_types": false,
"group_by": null
}
}{
"error": {
"code": "INVALID_REQUEST",
"message": "end_date must be later than start_date",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "A valid API key is required",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Resource not found",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "METHOD_NOT_ALLOWED",
"message": "This resource supports GET",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "Request limit exceeded",
"request_id": "example-request",
"details": []
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "Unable to complete request",
"request_id": "example-request",
"details": []
}
}Authorizations
Existing Breezy API key. Grants all published reads in its associated company. No app permission scopes.
Query Parameters
Maximum parent records or report rows. Complete children are always included.
1 <= x <= 100Repeat the original filters; any valid page size may continue. Foreign-company, tampered or mismatched cursors return INVALID_CURSOR.
1Inclusive company-local date.
Exclusive company-local date; must be after start_date.
day, week, month, quarter, year SERVICE, MAINTENANCE, ESTIMATE_REPAIR, ESTIMATE_REPLACE, INSTALL, WARRANTY, CALLBACK, SALES, UNKNOWN, null business_unit, job_type, job_class, null A validated assigned member. Selects distinct jobs for job financials/profitability and only that member for the participation report.
Include excluded or unavailable job-type mappings. Disabled costing and untracked jobs remain excluded.
Response
Successful read. Clients ignore unrecognized response fields.