Skip to content

Public API

Sina Gulsen edited this page May 29, 2026 · 5 revisions

Public API

The Effort Tracker Public API provides read-only programmatic access to your organization's effort tracking data. Use it to build integrations, generate custom reports, or sync data with external systems.

Base URL

https://efforttrackerapi.sinaware.com/api/v1/

Interactive Documentation (Swagger)

Explore and test the API interactively using the built-in Swagger UI:

Swagger UI

The OpenAPI specification is available at:

https://efforttrackerapi.sinaware.com/api/openapi/v3.json

Using Swagger UI

  1. Open the Swagger UI link above
  2. Click Authorize and enter your Azure DevOps PAT in the bearer token field
  3. For each endpoint, fill in the X-Organization header parameter with your Azure DevOps organization name (e.g., myorganization)
  4. Fill in any other required parameters and click Execute

Note: The X-Organization header is required for all endpoints. Swagger UI will show it as a required parameter field on each endpoint.

Authentication

All requests require an Azure DevOps Personal Access Token (PAT) and organization name.

Required Headers

Header Description Example
Authorization Bearer token with your Azure DevOps PAT Bearer your-pat-token
X-Organization Your Azure DevOps organization name myorganization

Getting a PAT

  1. Go to https://dev.azure.com/{your-org}/_usersSettings/tokens
  2. Click New Token
  3. Select scopes: Work Items (Read) minimum
  4. Copy the generated token

Example Request

curl -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: your-org-name" \
     https://efforttrackerapi.sinaware.com/api/v1/stats/summary

Rate Limits

The API enforces rate limits to ensure fair usage:

Limit Value
Per-token per minute 30 requests
Per-token per hour 250 requests
Per-organization per minute 100 requests
Export endpoint per hour 10 requests

Rate Limit Headers

Every response includes rate limit information:

Header Description
X-RateLimit-Remaining Requests remaining in the current window
X-RateLimit-Reset Unix timestamp when the limit resets

When rate limited, you'll receive a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait.

Response Format

All responses follow a standard envelope:

{
  "data": [...],
  "pagination": {
    "page": 1,
    "pageSize": 50,
    "totalCount": 234,
    "totalPages": 5
  },
  "meta": {
    "requestedAt": "2026-05-08T12:00:00Z"
  }
}
  • data — The response payload
  • pagination — Present on paginated endpoints
  • meta — Request metadata

Endpoints


GET /effortlogs

Get paginated effort logs for a specific work item.

Parameters:

Parameter Type Required Description
workItemId integer Yes Azure DevOps work item ID
page integer No Page number (default: 1)
pageSize integer No Results per page (default: 50, max: 500)

Example:

curl -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: myorg" \
     "https://efforttrackerapi.sinaware.com/api/v1/effortlogs?workItemId=123&page=1&pageSize=25"

Response:

{
  "data": [
    {
      "id": "abc-123",
      "workItemId": 123,
      "date": "2026-05-01",
      "hours": 2.5,
      "activityType": "Development",
      "notes": "Implemented feature X",
      "userId": "user-guid",
      "userDisplayName": "John Doe",
      "projectName": "MyProject",
      "areaPath": "MyProject\\Backend",
      "createdAt": "2026-05-01T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 25,
    "totalCount": 42,
    "totalPages": 2
  },
  "meta": {
    "requestedAt": "2026-05-08T12:00:00Z"
  }
}

POST /effortlogs/query

Query effort logs with advanced filters. Use POST because the filter body can be complex.

Request Body:

{
  "dateFrom": "2026-01-01",
  "dateTo": "2026-03-31",
  "usernames": ["John Doe", "Jane Smith"],
  "areas": ["MyProject\\Backend"],
  "workItemIds": [100, 101, 102],
  "activityTypes": ["Development", "Testing"],
  "projects": ["MyProject"],
  "notes": "search text",
  "page": 1,
  "pageSize": 50,
  "sortBy": "date",
  "sortDesc": true
}

All filter fields are optional. Only include the ones you need.

Field Type Description
dateFrom string Start date (YYYY-MM-DD)
dateTo string End date (YYYY-MM-DD)
usernames string[] Filter by display names
areas string[] Filter by area paths
workItemIds integer[] Filter by work item IDs
activityTypes string[] Filter by activity types
projects string[] Filter by project names
notes string Search within notes (contains)
page integer Page number (default: 1)
pageSize integer Results per page (default: 50, max: 500)
sortBy string Sort field: date, hours, activityType, userDisplayName, projectName, areaPath
sortDesc boolean Sort descending (default: true)

Example:

curl -X POST \
     -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: myorg" \
     -H "Content-Type: application/json" \
     -d '{"dateFrom":"2026-01-01","dateTo":"2026-03-31","pageSize":100}' \
     "https://efforttrackerapi.sinaware.com/api/v1/effortlogs/query"

GET /effortlogs/export

Export effort logs as CSV or JSON. Rate limited to 10 requests per hour.

Parameters:

Parameter Type Required Description
format string No csv or json (default: json)
dateFrom string No Start date (YYYY-MM-DD)
dateTo string No End date (YYYY-MM-DD)
usernames string No Comma-separated usernames
areas string No Comma-separated area paths
activityTypes string No Comma-separated activity types
projects string No Comma-separated project names

Example (CSV):

curl -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: myorg" \
     "https://efforttrackerapi.sinaware.com/api/v1/effortlogs/export?format=csv&dateFrom=2026-01-01" \
     -o export.csv

Example (JSON):

curl -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: myorg" \
     "https://efforttrackerapi.sinaware.com/api/v1/effortlogs/export?format=json&dateFrom=2026-01-01"

CSV Output Columns:

Id, WorkItemId, Date, Hours, ActivityType, Notes, UserId, UserDisplayName, ProjectName, AreaPath, CreatedAt

GET /activitytypes

Get all active activity types configured for the organization.

Parameters:

Parameter Type Required Description
project string No Filter by project name

Example:

curl -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: myorg" \
     "https://efforttrackerapi.sinaware.com/api/v1/activitytypes"

Response:

{
  "data": [
    {
      "id": "development",
      "name": "Development",
      "isActive": true,
      "displayOrder": 1,
      "projectName": "MyProject"
    },
    {
      "id": "testing",
      "name": "Testing",
      "isActive": true,
      "displayOrder": 2,
      "projectName": "MyProject"
    }
  ],
  "meta": {
    "requestedAt": "2026-05-08T12:00:00Z"
  }
}

GET /stats/summary

Get summary statistics for the entire organization.

Example:

curl -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: myorg" \
     "https://efforttrackerapi.sinaware.com/api/v1/stats/summary"

Response:

{
  "data": {
    "totalRecords": 1250,
    "totalHours": 4567.5,
    "userCount": 12,
    "projectCount": 5
  },
  "meta": {
    "requestedAt": "2026-05-08T12:00:00Z"
  }
}

GET /stats/user-counts

Get the number of effort log entries per user.

Parameters:

Parameter Type Required Description
project string No Filter by project name

Example:

curl -H "Authorization: Bearer YOUR_PAT" \
     -H "X-Organization: myorg" \
     "https://efforttrackerapi.sinaware.com/api/v1/stats/user-counts"

Response:

{
  "data": [
    { "user": "John Doe", "count": 150 },
    { "user": "Jane Smith", "count": 98 }
  ],
  "meta": {
    "requestedAt": "2026-05-08T12:00:00Z"
  }
}

Error Responses

All errors follow this format:

{
  "error": "Description of what went wrong"
}

HTTP Status Codes

Code Meaning
200 Success
400 Bad Request — Invalid parameters or request body
401 Unauthorized — Invalid or missing token
429 Too Many Requests — Rate limit exceeded
500 Internal Server Error — Something went wrong on our end

Code Examples

Python

import requests

BASE_URL = "https://efforttrackerapi.sinaware.com/api/v1"
HEADERS = {
    "Authorization": "Bearer YOUR_PAT",
    "X-Organization": "your-org-name"
}

# Get summary stats
response = requests.get(f"{BASE_URL}/stats/summary", headers=HEADERS)
stats = response.json()["data"]
print(f"Total hours: {stats['totalHours']}")

# Query effort logs
query = {
    "dateFrom": "2026-01-01",
    "dateTo": "2026-03-31",
    "activityTypes": ["Development"],
    "pageSize": 100
}
response = requests.post(f"{BASE_URL}/effortlogs/query", json=query, headers=HEADERS)
logs = response.json()["data"]

PowerShell

$headers = @{
    "Authorization" = "Bearer YOUR_PAT"
    "X-Organization" = "your-org-name"
}

# Get summary stats
$stats = Invoke-RestMethod -Uri "https://efforttrackerapi.sinaware.com/api/v1/stats/summary" `
    -Headers $headers
Write-Host "Total hours: $($stats.data.totalHours)"

# Query effort logs
$body = @{
    dateFrom = "2026-01-01"
    dateTo = "2026-03-31"
    pageSize = 100
} | ConvertTo-Json

$logs = Invoke-RestMethod -Uri "https://efforttrackerapi.sinaware.com/api/v1/effortlogs/query" `
    -Headers $headers -Method Post -Body $body -ContentType "application/json"

JavaScript / Node.js

const BASE_URL = "https://efforttrackerapi.sinaware.com/api/v1";
const headers = {
  "Authorization": "Bearer YOUR_PAT",
  "X-Organization": "your-org-name",
  "Content-Type": "application/json"
};

// Get summary stats
const statsRes = await fetch(`${BASE_URL}/stats/summary`, { headers });
const stats = await statsRes.json();
console.log(`Total hours: ${stats.data.totalHours}`);

// Query effort logs
const queryRes = await fetch(`${BASE_URL}/effortlogs/query`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    dateFrom: "2026-01-01",
    dateTo: "2026-03-31",
    pageSize: 100
  })
});
const logs = await queryRes.json();

Notes

  • The public API is read-only. Create/update/delete operations are only available through the Azure DevOps extension UI.
  • All dates use YYYY-MM-DD format.
  • The API returns data scoped to the organization specified in the X-Organization header.
  • Your PAT must have access to the specified organization.
  • Maximum page size is 500 records per request.

Effort Tracker Wiki

Getting Started

User Guides

Administration

Reference


Links

Clone this wiki locally