Get tracked hours for an opportunity

GET
/opportunities/{opportunityId}/hours

Hours each expert worked on this opportunity, one row per person and date. Time spent on your other opportunities, and time clocked in but not spent on work, is not included. The current day is partial and refreshes through the day; last_updated_at says when the hours were last refreshed.

Authorization<token>

API key as Bearer token: Authorization: Bearer

In: header

Path Parameters

opportunityId*string

ID of the opportunity, as returned by POST /opportunities or GET /opportunities.

Query Parameters

from*string

Start of the window, inclusive: an ISO 8601 UTC timestamp such as 2026-09-08T00:00:00Z, or a bare 2026-09-08 read as midnight UTC. A person's day counts when the instant it opened in their own tracker timezone falls in the window, so a day is never returned in halves.

to*string

End of the window, exclusive, in the same UTC form: a day that opened exactly at to belongs to the next window, so consecutive requests neither double count nor skip. At most 92 days after from.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://terac.com/api/external/v2/opportunities/string/hours?from=string&to=string"
{
  "last_updated_at": "string",
  "total_seconds": 0,
  "total_hours": 0,
  "data": [
    {
      "participant_id": "string",
      "submission_id": "string",
      "email": "string",
      "date": "string",
      "timezone": "string",
      "seconds": 0,
      "hours": 0
    }
  ]
}
{
  "code": "BAD_REQUEST",
  "message": "Invalid input data",
  "issues": []
}

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "API key required. Include Authorization: Bearer <key> header."
  }
}

{
  "error": {
    "code": "FORBIDDEN",
    "message": "This account is not permitted to use the API."
  }
}

{
  "code": "NOT_FOUND",
  "message": "Not found",
  "issues": []
}
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 61 seconds."
  }
}
{
  "code": "INTERNAL_SERVER_ERROR",
  "message": "Internal server error",
  "issues": []
}