Harvest API integration for session-log → time-entry + report pulls — PARKED

DARE.CO.UK · PARKED SKETCH · 2026-05-20

Mirrored from ~/.claude/.../memory/project_harvest_api_integration_parked.md. This is a design sketch parked for future build — read for context, not as a current deliverable.

Dan 2026-05-20 asked if Harvest’s API supports two-way: push dev-session logs into Harvest as time entries (annotated with what we worked on) + pull down reports (revenue, time per project, expense summaries). Yes — Harvest has a documented REST API v2 with personal access tokens. Resume when one of the build triggers fires.


Dan, 2026-05-20:

“can you also make a note to see if the api is open for getharvest.com — we log expenses and time into it, I would love to be able to carry session logs into it for the business, and pull down reports”

Quick answer — yes, the API is open

Harvest publishes REST API v2 with documentation at https://help.getharvest.com/api-v2/ (verified 200 today). Authentication via Personal Access Tokens (or OAuth 2.0 for multi-user apps). Tokens minted at https://id.getharvest.com/developers (verified 200).

Capabilities relevant to Dan’s two asks:

What Dan wants Harvest API endpoint
Push session logs as time entries POST /v2/time_entries — date · hours · project_id · task_id · notes (free-text where session log goes)
Pull down reports — revenue GET /v2/reports/uninvoiced + GET /v2/reports/expenses
Pull down reports — time per project GET /v2/reports/time/projects + GET /v2/reports/time/clients
Pull expenses for tax/accounting GET /v2/expenses
List projects/tasks to map session work onto GET /v2/projects + GET /v2/tasks

The build shape (mirrors gsc_pull.py + would-be ebay_pull.py)

Same shape we’ve now codified as the portfolio-standard API integration pattern:

~/bin/harvest_push.py          # converts session report → time entry
  ├─ reads ~/Downloads/dare_session_report_<date>.md
  ├─ parses date, total hours, project tag (which client/project the work was for)
  ├─ POST /v2/time_entries with notes = session-report URL + headline
  └─ idempotent — re-running same day updates the entry, doesn't dupe

~/bin/harvest_pull.py          # pulls reports → markdown
  ├─ GET /v2/reports/uninvoiced (revenue accrued, not yet invoiced)
  ├─ GET /v2/reports/time/projects (week + month + quarter rollups)
  ├─ GET /v2/expenses (recent expense entries with receipts)
  └─ writes ~/Downloads/harvest_pull_<date>.md

# Optional Phase B:
~/bin/harvest_session_link.sh  # appended to dare_session_report → auto-push

Credentials

Harvest auth needs: - Personal Access Token — minted at id.getharvest.com/developers (Dan does this once, takes ~1 min) - Account ID — shown alongside the token on the same page - Both stored in 1Password as custom-named concealed fields per feedback_1password_custom_concealed_fields.md: - Suggested item name: Harvest API - Custom fields: account_id (concealed) + personal_access_token (concealed) - References: op://Code Shared/Harvest API/account_id + op://Code Shared/Harvest API/personal_access_token

No OAuth dance needed for personal tokens — simpler than GSC or eBay setup.

Cost

Item Cost
Harvest account Dan’s existing subscription (already paying — this is just adding the API surface)
API calls $0 within rate limits
Rate limit 100 requests / 15-second window per account — way more than enough
Marginal cost $0

Build estimate (when triggered)

Step Effort Notes
1. Personal access token + 1Password storage 5 min Dan does it
2. harvest_pull.py — basic reports pull 60 min Test against live, no sandbox needed
3. harvest_push.py — session-log → time entry 75 min Project/task mapping needs a small lookup table (which dare/audrey/etc project = which Harvest project)
4. Wire into existing session-report chain 20 min Optional auto-trigger after dare_session_report.py finishes

Total: ~2.5 hours for full bidirectional integration.

Compelling angle — bidirectional value

Most portfolio API integrations are one-way (pull data into the toolkit). Harvest is rare in that it’s bidirectional and the push side has unique leverage:

The downstream effect: the time-tracking step (Harvest) stops being a separate ritual Dan has to remember; it becomes automatic when the session report renders. The data already exists; Harvest just becomes its accounting interface.

Resume conditions (build when ANY hold)

  1. Dan complains about manual Harvest time-entry overhead — same friction signal as the eBay sketch
  2. A client engagement starts that needs detailed time logging — auto-push of session reports as time entries becomes load-bearing
  3. Tax-time approaches and Dan wants automated expense + time rollups in the catalog
  4. The eBay integration ships first — Harvest then becomes the second instance of the OAuth-pull-render template (eBay being the first), so cost-per-additional-integration drops

Skip / defer if

Sibling memories

The aphorism

The session report already knows what we did. Harvest just needs to know how long. The integration is the bridge, not the source.

Source: parked_sketch_harvest_api_integration_2026-05-20.md · Rendered 2026-05-20 18:23