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=100Paginate 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=100Paginate 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=100Step 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_idvalues — 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=100Step 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=1Walk 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=20On 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_YorkThe response is a bare array of activity-block records. Each block covers a 10-minute window and includes:
activity— keyboard/mouse activity percentagescreen_count— number of screens capturedscreenshots— array of entries, each withtimestamp,imageURL,thumbnailURL, andscreen_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:
- Fetch the member list.
- For each
(user_id, date)combination, callGET /v1/screenshots/. - 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=100Paginate. 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=100Walk 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=100Incremental 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=100Walk 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=100Call 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=100Run 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=paidPaginate 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=100start_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=20Each 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=20Tip: 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 queriesplan.max_members— to know if member onboarding is at capacityconfiguration.screenshot_interval— screenshots-per-hour settingconfiguration.track_apps/track_urls— whether app and URL data is availableidle_time_setting— how idle time is handled (useful for interpretingidle_timesin 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.
