Contracts

Use this endpoint to retrieve a paginated list of contracts within your agency, ordered by start date (most recent first).

A contract represents an ongoing engagement where a contractor works for a client company on a project. Each row is a lightweight summary — use Get contract details (GET /api/v1/contracts/{id}) to drill into a single contract's rates, contacts, attributions, and allowances.

Contract hires vs permanent hires: Contract financials and schedule live on the contract, not on the placement. Use this endpoint (plus the detail endpoint) for contract engagements — it is the only source of endDate and of the charge/pay rates. Keep using GET /api/v1/placements for permanent hires (salary) and for fee attribution on both hire types. GET /api/v1/placements does not embed contract rates or contract end dates.

What you can filter by (filters combine with AND semantics):

  • status - one or more of draft, scheduled, active, ended, terminated, cancelled (comma-separated)
  • projectId / contractorId / clientCompanyId - the linked project, contractor person, or end client company
  • ownerEmail - one or more contract owner emails (comma-separated)
  • startDateFrom / startDateTo - only contracts whose start date falls in this range (YYYY-MM-DD, both bounds inclusive)
  • createdAfter / createdBefore - only contracts created within a specific date range
  • updatedAfter / updatedBefore - only contracts last modified within a specific date range (ISO 8601). Filters on the updatedAt field

Incremental sync: To keep an external copy in sync, use updatedAfter as a cursor: on each run, request updatedAfter=<the highest updatedAt you have seen so far>, page through the results, and persist the maximum updatedAt across the rows you receive. Pass that stored value as updatedAfter on the next run to fetch only records that changed since. Because the bound is inclusive you may re-receive the boundary row — upsert by id to stay idempotent. Editing a contract's end date or any of its rates bumps updatedAt, so rate changes surface on the next poll; fetch GET /api/v1/contracts/{id} for the rows whose rates you need.

Pagination: Results are returned in pages. Use the page and pageSize parameters to move through large result sets. The response includes a pagination object with page, pageSize, total, and totalPages.

What you get back: Each contract in the list includes its status and schedule (startDate, endDate, derived durationDays), references to the client company, project, contractor, and owner, and the four pre-calculated financials (weeklyRevenue, weeklyGp, monthlyRevenue, monthlyGp) in the agency base currency — null for contracts with no rates yet. Rates are intentionally not on the list rows; read them from the detail endpoint.

Deletions (tombstones): Soft-deleted contracts are excluded by default. Pass includeDeleted=true to also receive deleted contracts as tombstones — each carries a populated deletedAt (live rows have deletedAt: null). Combine includeDeleted=true with updatedAfter to incrementally pick up deletions: a soft-delete bumps updatedAt, so the deleted row resurfaces in the next poll with deletedAt set.

clientCompany, project, contractor and owner are always present, including on tombstones and when the referenced record has itself been deleted in Atlas — you will still receive its id and name so you can reconcile against your own copy.

get/api/v1/contracts

Request

Query parameters

statusstring

Comma-separated contract statuses to filter by. Options: draft, scheduled, active, ended, terminated, cancelled

Example:active,scheduled
projectIdstring uuid

Filter by linked project ID

Example:550e8400-e29b-41d4-a716-446655440001
contractorIdstring uuid

Filter by contractor (person) ID

Example:550e8400-e29b-41d4-a716-446655440002
clientCompanyIdstring uuid

Filter by end client company ID

Example:550e8400-e29b-41d4-a716-446655440003
ownerEmailstring

Comma-separated contract owner emails

Example:owner1@agency.com,owner2@agency.com
startDateFromstring

Only contracts with startDate on or after this date (YYYY-MM-DD, inclusive)

Example:2026-01-01
startDateTostring

Only contracts with startDate on or before this date (YYYY-MM-DD, inclusive)

Example:2026-12-31
string
OR
string date-time
string
OR
string date-time
string
OR
string date-time
string
OR
string date-time
includeDeleted'true' | 'false'

Include soft-deleted contracts as tombstones (with a populated deletedAt). Defaults to false. Pair with updatedAfter to incrementally sync deletions.

Example:false
pageinteger

Page number (1-indexed)

Example:1
pageSizeinteger

Items per page (max 100)

Example:25
perPageinteger

Alias for pageSize

Response

Paginated list of contracts

status'ok' required

Example response

{
  "data": [
    {
      "status": "active",
      "startDate": "2026-04-01",
      "endDate": "2026-06-30",
      "durationDays": 90,
      "clientCompany": {
        "name": "Bullhorn Inc"
      },
      "project": {
        "jobRole": "Software Developer"
      },
      "contractor": {
        "firstName": "Eveling",
        "lastName": "Garcia"
      },
      "owner": {
        "email": "jordan@agency.com",
        "name": "Jordan Smith"
      },
      "weeklyRevenue": "4000.00",
      "weeklyGp": "800.00",
      "monthlyRevenue": "17333.33",
      "monthlyGp": "3466.67"
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 25,
    "total": 1,
    "totalPages": 1
  }
}

Changes