Upwork public GraphQL: timeReport returns 403 team-action denial, workDiaryCompany returns empty, but internal agencyCompanyTimeReport returns data
08:10 07 Apr 2026

I’m trying to get agency weekly timesheet data from Upwork via OAuth2 (official/public API).

I can successfully authorize as a user who has access in UI, and I can switch org context using tenant header.

Environment

  • Endpoint (public): https://api.upwork.com/graphql

  • OAuth2: user token (oauth2v2_pub_*)

  • Tenant header: X-Upwork-API-TenantId:

  • Library: python-upwork-oauth2

What works

whoami shows tenant context is switched correctly:

query {
  user { id nid }
  organization { id rid name }
}

Without tenant header -> personal org
With tenant header -> agency org (expected)

What fails on public API

1) timeReport / contractTimeReport return 403 action denial

query($filter: TimeReportFilter!) {
  timeReport(filter: $filter) { totalHoursWorked }
}

Variables:

{
  "filter": {
    "organizationId_eq": "",
    "timeReportDate_bt": {
      "rangeStart": "20260406",
      "rangeEnd": "20260407"
    }
  }
}

Error:

User  has no access of any team(s) for [view_gds_hourly_data_from_client, view_gds_charges_data_from_client] action(s)

2) workDiaryCompany returns empty data (no errors)

query($input: WorkDiaryCompanyInput!) {
  workDiaryCompany(workDiaryCompanyInput: $input) {
    total
    snapshots {
      user { id name }
      contract { id contractTitle }
      durationInt
    }
  }
}

Variables:

{
  "input": {
    "companyId": "",
    "date": "20260406"
  }
}

Response: snapshots=[], no errors (same for multiple dates, including long ranges)

Confusing part

The internal web endpoint used by Upwork UI: https://www.upwork.com/api/graphql/v1?alias=agencyCompanyTimeReport (with browser session / oauth2v2_int_*) returns correct agency rows for the same date range and same agency company UID.

But in public API schema (api.upwork.com/graphql), agencyCompanyTimeReport is not available (FieldUndefined).

P.S.: The user on whose behalf the authorization is performed has all the following Roles granted within the agency: Team work diary access, Company-wide chat access, Team-only chat access, Agency exclusive contractor, Agency manager, Account admin, Finance admin, API Key Manager.

Question

What is the official supported public API method to get agency weekly summary by freelancer (hours/charges/contracts) if:

  • timeReport is denied by team actions,

  • contractTimeReport is denied similarly,

  • workDiaryCompany is empty,

  • and agencyCompanyTimeReport exists only on internal web GraphQL?

Is this strictly a permissions provisioning issue on Upwork side, or is this data path not available via public API at all?

oauth-2.0 graphql upwork-api