Skip to content

Use Cases

Practical integration patterns for common partner use cases — as direct REST calls you write and run yourself below, or conversationally through an AI client connected over MCP (see MCP overview). The AI Assistant Queries section near the end maps several of these same workflows to natural-language prompts and the MCP tools behind them.


Payroll Export

Export all member hours and one-time payments for a given month for payroll processing.

Step 1 — Fetch the member list

GET /v1/members/?limit=100

Paginate through all pages until next is null. Collect user_id for each member.

Step 2 — Fetch hourly payment records per member

GET /v1/members/{user_id}/hourly_payment_logs/?start_date=2026-05-01&end_date=2026-05-31&limit=100

Paginate through all pages. Each record includes paid_for_date, working_duration, pay_rate, amount, and currency.

Step 3 — Fetch one-time payments per member

GET /v1/members/{user_id}/one_time_payment_logs/?start_date=2026-05-01&end_date=2026-05-31&limit=100

Step 4 — Fetch current pay rates for reference

GET /v1/members/{user_id}/payment_settings/

Returns the full rate history as a bare array. The entry with end=null is the current rate.

Tips

  • Fetch the org timezone first (GET /v1/organizations/) and pass it to all payment log queries so date boundaries align with what Apploye shows.
  • For organizations with many members, parallelize across user_id values — each request is independent and the rate limit is per org per endpoint (not per member).
  • Payment amounts are in major currency units (dollars/euros, not cents).

Activity Report Sync

Sync daily time-and-activity data into an external analytics or BI system.

Step 1 — Discover which members to sync

GET /v1/members/?limit=100

Step 2 — Fetch time activity report in 31-day windows

GET /v1/time_activity_reports/?start_date=2026-01-01&end_date=2026-01-31&limit=20&page=1

Walk pages until next is null. Each result item contains a user and a days array with per-day time_worked, idle_time, and activity percentage.

For custom team filters:

GET /v1/time_activity_reports/?start_date=2026-01-01&end_date=2026-01-31&team_id={team_id}

Note: user_id and team_id are mutually exclusive on this endpoint.

Incremental sync strategy

Track the last-synced date per user_id. On each run, fetch from last_synced_date to today in 31-day windows. Use user.user_id as the join key. Upsert records by (user_id, date) to handle updates.


Timesheet Import into External System

Import detailed timesheet entries including idle-time segments.

Cursor-based walk

GET /v1/timesheet_idle_times/?start_date=2026-05-01&end_date=2026-05-31&limit=20

On the first call, omit cursor. On subsequent calls, pass pagination.next_cursor from the previous response:

GET /v1/timesheet_idle_times/?start_date=2026-05-01&end_date=2026-05-31&limit=20&cursor=eyJ1c2VyX2lkIjoiLi4uIn0=

Repeat until pagination.has_more is false.

Each result item contains a user and their timesheets for the period. Timesheets include project, task, is_manual, is_approved, and nested idle_times.

Upsert by ID

Use timesheets[].id (UUID) as the primary key in your system. Timesheets can be modified after creation (the modified_flag field indicates this). Always upsert rather than insert to pick up corrections.

Large organizations

For orgs with many users, reduce limit to 10 (the default) to avoid very large response payloads. The cursor handles continuation regardless of limit.


Screenshot Audit Trail

Retrieve screenshot evidence for a specific member on a specific date.

GET /v1/screenshots/?user_id={user_id}&date=2026-05-15&timezone=America/New_York

The response is a bare array of activity-block records. Each block covers a 10-minute window and includes:

  • activity — keyboard/mouse activity percentage
  • screen_count — number of screens captured
  • screenshots — array of entries, each with timestamp, image URL, thumbnail URL, and screen_number

Download screenshots

image and thumbnail are signed or public CloudFront URLs. Fetch them directly with HTTP GET. They are null when the file was not uploaded.

Walking multiple members and dates

The screenshots endpoint is per-user per-day. For team-level screenshot exports:

  1. Fetch the member list.
  2. For each (user_id, date) combination, call GET /v1/screenshots/.
  3. Parallelize per-user calls (all are independent).

Maximum lookback: 179 days. For dates older than 179 days, the API returns 404.


Project & Task Listing

Sync the project and task tree into an external project management tool. For org-wide polling, use the flat list endpoints instead of nested fan-out.

All projects

GET /v1/projects/?limit=100

Paginate. The response includes is_active — filter locally if you only want active projects.

Incremental task sync (polling)

Poll tasks org-wide instead of calling /v1/projects/{project_id}/tasks/ for every project:

GET /v1/tasks/?updated_since=2026-06-01T12:00:00Z&limit=100

Walk pages until next is null. Each result includes project_id and updated_at. Upsert by task id. Use the newest updated_at seen as the next poll's updated_since value.

To narrow to one project, add project_id:

GET /v1/tasks/?project_id={project_id}&updated_since=2026-06-01T12:00:00Z&limit=100

Incremental project-membership sync (polling)

Poll assignments org-wide instead of calling /v1/members/{user_id}/projects/ or /v1/projects/{project_id}/members/ for every member or project:

GET /v1/project_memberships/?updated_since=2026-06-01T12:00:00Z&limit=100

Walk pages until next is null. Each result is a junction row with user_id, project_id, permissions, and updated_at. Upsert by id (or by (user_id, project_id)). Use the newest updated_at seen as the next poll's updated_since value.

Task assignee sync

The task_new_members junction table has no updated_at, so there is no org-wide incremental endpoint for task assignments. For task-field changes:

GET /v1/tasks/?updated_since=2026-06-01T12:00:00Z&limit=100
GET /v1/tasks/{task_id}/members/?limit=100

Call the nested members route for each task returned by the tasks poll. This does not catch assignment-only changes on tasks whose fields did not change.

Project members and tasks (on-demand drill-down)

GET /v1/projects/{project_id}/members/?limit=100
GET /v1/projects/{project_id}/tasks/?limit=100

Run these in parallel. Each is independent. Prefer GET /v1/tasks/ and GET /v1/project_memberships/ for org-wide polling; use per-parent nested routes when you need embedded detail or already know the parent ID.

Billable rates per project

GET /v1/projects/{project_id}/billable/

Returns billable_type, project_hourly.rate, and person_hourlies with per-member rates.


Invoice Export to Accounting System

All invoices

GET /v1/invoices/?limit=100&status=paid

Paginate with page. Filter by status (draft, sent, paid, overdue) and client_id as needed.

Invoice detail for booking entries

GET /v1/invoices/{invoice_id}/

Returns line items, tax rates, discount, payments, and computed totals. All amounts are in major currency units. paid_amount is the sum of all recorded payments.

Monthly invoice reconciliation

GET /v1/invoices/?start_date=2026-05-01&end_date=2026-05-31&status=paid&limit=100

start_date / end_date filter on issued_date. Walk pages to collect all invoices issued in the month, then fetch detail for each.


App/URL Usage Report

Identify which applications team members spent time in over a week.

GET /v1/app_reports/?start_date=2026-06-23&end_date=2026-06-29&timezone=UTC&limit=20

Each result item contains a user, working_day (YYYY-MM-DD), app_data array (sorted by most time first), and total_time.

For URL tracking:

GET /v1/url_reports/?start_date=2026-06-23&end_date=2026-06-29&timezone=UTC&limit=20

Tip: App and URL data is captured only when the Apploye desktop agent is running with tracking enabled. Members who track time via the web or mobile app only may have no app/URL data.


Organization Health Check

Retrieve high-level org metadata for an onboarding or configuration check.

GET /v1/organizations/

Returns:

  • timezone — use this for all subsequent date-range queries
  • plan.max_members — to know if member onboarding is at capacity
  • configuration.screenshot_interval — screenshots-per-hour setting
  • configuration.track_apps / track_urls — whether app and URL data is available
  • idle_time_setting — how idle time is handled (useful for interpreting idle_times in timesheets)

AI Assistant Queries (via MCP)

Some of the workflows above — pagination walks, per-member fan-out, manual aggregation — are exactly what an AI client can do for you conversationally once it's connected over MCP (see MCP overview and Connecting an AI client). You ask a question in plain language; the client picks the right tool(s), handles pagination itself, and returns an answer instead of raw pages of JSON. This section maps a few of the REST workflows above to their MCP equivalent — useful for internal/ad hoc questions where you don't want to write or maintain integration code at all.

"What did each team member earn in hourly pay last month?"

The REST version of this is Payroll Export's Steps 1–2 (list members, then walk hourly payment logs per member). An AI client with payroll:read answers this in one call to get_member_payables_summary(start_date, end_date) — a per-member payables total for the range, no manual fan-out required.

"Is Project X on track against its budget?"

Comparison tools like get_project_hours_comparison are bounded to two date ranges (each capped at 31 days) — fine for "this month vs. last," but the wrong tool if the real question is lifetime hours against a budget, since a project's tracked history can predate its own start_date. For that specific question, get_project_lifetime_tracked_hours(project_id) returns true all-time tracked seconds, no date range at all — the tool to reach for when "on track" means "ever," not "this period."

"Which members logged manually-created timesheet entries this week, and how many each?"

Don't confuse this with list_manual_timesheet_reports, which tracks manual corrections to existing entries (timesheetupdatelogs) — a different concept. For counting entries that were manually created (timesheets.is_manual = true), the right tool is get_manual_timesheet_entry_counts(start_date, end_date), a direct per-member count, descending — no need to fetch every timesheet and filter locally the way the REST Timesheet Import workflow above would.

"How has member X's daily activity trended over the last 30 days?"

Equivalent to the Activity Report Sync workflow's per-day time_worked/activity fields, but pre-aggregated into a day-by-day series: get_activity_trend(start_date, end_date, user_id) returns one row per calendar day (including zero-activity days, never silently omitted), instead of the paginated per-user report the REST endpoint returns.

"What were the top apps and URLs used org-wide this week?"

The REST App/URL Usage Report above is per-user, per-day — org-wide "top apps" requires fetching every user's data and aggregating it yourself. get_app_usage_top_org_wide(start_date, end_date) and get_url_usage_top_org_wide(start_date, end_date) do that aggregation server-side and return a ranked list directly.

What AI queries can't do (yet)

MCP tools are read-only in v1 (see MCP overview) — none of the above writes anything. For genuinely bulk/scheduled work (nightly payroll exports, a BI pipeline's incremental sync), the REST workflows above are still the right tool: they're built for pagination at scale and don't depend on an AI client being connected. Reach for MCP for ad hoc questions and one-off checks, REST for anything you're automating or running unattended.