---
title: costs.jobs | Doing Work API
description: Job costing across jobs dated between two days (inclusive, in the shop's time zone), with totals. Sort by profit (lowest first, to find the losers), margin
url: https://doingwork.work/docs/reference/costs-jobs/
---

# costs.jobs

Job costing across jobs dated between two days (inclusive, in the shop's time zone), with totals. Sort by profit (lowest first, to find the losers), margin, or date. Up to 500 jobs; truncated says when more matched.

|  |  |
|---|---|
| Who | Agents can call this |
| REST | `GET /v1/costs/jobs` |
| MCP tool | `costs_jobs` |
| Writes | no |
| Area | [Costs, expenses and reports](https://doingwork.work/docs/reference/#costs-expenses-and-reports) |

## When to use it

Job costing across jobs dated between two days (inclusive, in the shop's time zone), with totals. Sort by profit (lowest first, to find the losers), margin, or date.

## What to tell the owner

Tell them what you found in plain words. Don't read back raw fields.

## Input

| Field | Type | Required |
|---|---|---|
| `shop_id` | string (uuid) | yes |
| `from` | string | yes |
| `to` | string | yes |
| `status` | array | no |
| `sort` | string (one of profit, margin, date) | no |
| `limit` | integer | no |

## Example

```http
GET https://doingwork.work/v1/costs/jobs?shop_id=00000000-0000-4000-8000-000000000000&from=...&to=...
```

## Output

| Field | Type | Always there |
|---|---|---|
| `jobs` | array | yes |
| `jobs[].job_id` | string (uuid) | yes |
| `jobs[].kind` | string | yes |
| `jobs[].status` | string | yes |
| `jobs[].summary` | ['string', 'null'] | yes |
| `jobs[].customer_id` | ['string', 'null', ' ', '(', 'u', 'u', 'i', 'd', ')'] | yes |
| `jobs[].occurred_at` | string (date-time) | yes |
| `jobs[].currency` | string | yes |
| `jobs[].contract_minor` | integer | yes |
| `jobs[].invoiced_minor` | integer | yes |
| `jobs[].tax_minor` | integer | yes |
| `jobs[].draft_invoices_minor` | integer | yes |
| `jobs[].refunded_minor` | integer | yes |
| `jobs[].collected_minor` | integer | yes |
| `jobs[].revenue_minor` | integer | yes |
| `jobs[].labor_minutes` | integer | yes |
| `jobs[].labor_pending_minutes` | integer | yes |
| `jobs[].labor_cost_minor` | integer | yes |
| `jobs[].labor_pending_cost_minor` | integer | yes |
| `jobs[].uncosted_minutes` | integer | yes |
| `jobs[].running_clocks` | integer | yes |
| `jobs[].materials_cost_minor` | integer | yes |
| `jobs[].materials_price_minor` | integer | yes |
| `jobs[].uncosted_materials` | integer | yes |
| `jobs[].expenses_minor` | integer | yes |
| `jobs[].expenses_by_category` | object | yes |
| `jobs[].fees_minor` | integer | yes |
| `jobs[].cost_minor` | integer | yes |
| `jobs[].profit_minor` | integer | yes |
| `jobs[].margin` | ['number', 'null'] | yes |
| `jobs[].unbilled_minor` | integer | yes |
| `totals` | object | yes |
| `totals.jobs` | integer | yes |
| `totals.currency` | ['string', 'null'] | yes |
| `totals.margin` | ['number', 'null'] | yes |
| `totals.contract_minor` | integer | yes |
| `totals.invoiced_minor` | integer | yes |
| `totals.tax_minor` | integer | yes |
| `totals.draft_invoices_minor` | integer | yes |
| `totals.refunded_minor` | integer | yes |
| `totals.collected_minor` | integer | yes |
| `totals.revenue_minor` | integer | yes |
| `totals.labor_minutes` | integer | yes |
| `totals.labor_pending_minutes` | integer | yes |
| `totals.labor_cost_minor` | integer | yes |
| `totals.labor_pending_cost_minor` | integer | yes |
| `totals.uncosted_minutes` | integer | yes |
| `totals.materials_cost_minor` | integer | yes |
| `totals.materials_price_minor` | integer | yes |
| `totals.uncosted_materials` | integer | yes |
| `totals.expenses_minor` | integer | yes |
| `totals.fees_minor` | integer | yes |
| `totals.cost_minor` | integer | yes |
| `totals.profit_minor` | integer | yes |
| `totals.unbilled_minor` | integer | yes |
| `truncated` | boolean | yes |

```json
{
  "jobs": [
    {
      "job_id": "00000000-0000-4000-8000-000000000000",
      "kind": "...",
      "status": "...",
      "summary": "...",
      "customer_id": "00000000-0000-4000-8000-000000000000",
      "occurred_at": "...",
      "currency": "...",
      "contract_minor": 50000,
      "invoiced_minor": 50000,
      "tax_minor": 50000,
      "draft_invoices_minor": 50000,
      "refunded_minor": 50000,
      "collected_minor": 50000,
      "revenue_minor": 50000,
      "labor_minutes": 1,
      "labor_pending_minutes": 1,
      "labor_cost_minor": 50000,
      "labor_pending_cost_minor": 50000,
      "uncosted_minutes": 1,
      "running_clocks": 1,
      "materials_cost_minor": 50000,
      "materials_price_minor": 50000,
      "uncosted_materials": 1,
      "expenses_minor": 50000,
      "expenses_by_category": {},
      "fees_minor": 50000,
      "cost_minor": 50000,
      "profit_minor": 50000,
      "margin": "...",
      "unbilled_minor": 50000
    }
  ],
  "totals": {
    "jobs": 1,
    "currency": "...",
    "margin": "...",
    "contract_minor": 50000,
    "invoiced_minor": 50000,
    "tax_minor": 50000,
    "draft_invoices_minor": 50000,
    "refunded_minor": 50000,
    "collected_minor": 50000,
    "revenue_minor": 50000,
    "labor_minutes": 1,
    "labor_pending_minutes": 1,
    "labor_cost_minor": 50000,
    "labor_pending_cost_minor": 50000,
    "uncosted_minutes": 1,
    "materials_cost_minor": 50000,
    "materials_price_minor": 50000,
    "uncosted_materials": 1,
    "expenses_minor": 50000,
    "fees_minor": 50000,
    "cost_minor": 50000,
    "profit_minor": 50000,
    "unbilled_minor": 50000
  },
  "truncated": true
}
```

## Errors

| Code | Status | What to do |
|---|---|---|
| `invalid_input`, `invalid_token`, `rate_limited` |  | Can happen on any call. See [errors](https://doingwork.work/docs/errors/). |
