Paidwell API
A small REST API for logging consulting time, reading entries, managing projects, and pulling hours/revenue rollups. Any tool that can make an authenticated HTTP request — an agent platform, a cron script, curl — can drive it.
Paidwell ships a remote MCP server at /mcp (streamable HTTP, OAuth sign-in — no key handling). Add it as a custom connector and you get job-shaped tools — log_call, whats_unbilled, find_gaps — plus a drafts workflow where inferred work waits for your approval. Per-client setup lives in Settings → Connect your AI.
In Settings → API access create a key (pick a scope: full, log-only, or read-only), then hit Copy agent setup prompt. That copies a full instruction set — with your key and base URL baked in — that any agent can use to build a Paidwell skill. No manual wiring.
Every request needs a Paidwell API key (mint one under Settings → API access; the API is free on every plan, Free tier included). Send it as either header. Keys are secret — they can create, edit, and delete your billing data. Only a SHA-256 hash is stored; the raw paidwell_sk_… secret is shown once, at creation.
Authorization: Bearer paidwell_sk_… # or X-API-Key: paidwell_sk_…
Base URL: /api/v1 on this host. Verify a key:
curl https://<your-paidwell-host>/api/v1/ping \
-H "Authorization: Bearer paidwell_sk_…"
# → {"ok":true,"service":"paidwell","authenticatedAs":"<label>", …}All paths under /api/v1. Bodies and responses are JSON. Every request is scoped to the key owner’s own data.
?archived=true|false.name is required; call-billing fields are optional.{ "name": "Acme", "client": "Acme Inc", "hourlyRate": 200,
"callMinimumMinutes": 60, "callPaddingMinutes": 60, "roundToMinutes": 60 }projectId, from, to (YYYY-MM-DD, inclusive), billable, billed, search, limit (≤1000, default 100), proposed (true lists the draft approve-queue; drafts are excluded by default).projectId or project (name, case-insensitive); an optional non-Standard rate by rateId or rate (its label). Express duration three ways, and always pass an explicit date.# human duration string
{ "project": "Acme", "description": "Architecture review", "duration": "1h30m", "date": "2026-05-31" }
# explicit minutes
{ "project": "Acme", "description": "Bugfix", "durationMinutes": 45, "date": "2026-05-31" }
# a CALL — applies the project's billing rules (minimum → padding → rounding)
{ "project": "Acme", "description": "Kickoff call", "isCall": true, "bookedDuration": "1h" }Two agent-trust flags: "proposed": true lands the entry in the user’s in-app Inbox as a draft (invisible to every report until approved — use for anything inferred), and "dryRun": true computes the billing math and returns the would-be entry without saving anything.
description, date, durationMinutes, billable, billed, invoiceRef (send null to clear it), proposed (only false — approving a draft; an entry can never be demoted back to a draft).from, to, projectId. Returns { totals: { hours, billableHours, unbilledHours, revenueEstimate, unbilledRevenueEstimate, entryCount }, byProject: [...] }.from, to (≤92 days); optional minHours. Weekends skipped; future days are never gaps; drafts don’t count as logged.Keys carry a least-privilege scope chosen at mint time: full (read, log, edit, billing — your own agents), log (read + create entries only — a calendar bot), or read(read-only — a bookkeeper’s agent). Out-of-scope requests return 403.
When isCall: true, the booked duration is transformed by the project’s rules in order: minimum → + padding → round to nearest N (floored at one unit). Example: a 1h booked call with min 60, padding 60, round 60 bills 2h. A short call never collapses below one rounding unit.
Errors return { "error": { "code", "message" } } with a matching HTTP status: 400 bad_request · 401 unauthorized · 403 forbidden (revoked key) · 404 not_found · 429 rate_limited (>120 req/min per key) · 500 server_error.