Skip to content
Hoursmith Docs
API

Common workflows

End-to-end Hoursmith API examples — create a client and project, log time, and read back invoices.

These walkthroughs stitch the endpoints together into real tasks. They assume a $TOKEN environment variable holding your API token and use the base URL https://hoursmith.app/api/v1.

Set up a client and project

# 1. Create a client (POST requires an Idempotency-Key)
curl https://hoursmith.app/api/v1/clients \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Globex", "email": "billing@globex.com", "currency": "USD" }'

# Response: { "data": { "id": "cl_...", "name": "Globex", ... } }

# 2. Create an hourly project for that client
curl https://hoursmith.app/api/v1/projects \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "clientId": "cl_...", "name": "Website redesign" }'

See the exact accepted fields on Create a client and Create a project.

Log time

The canonical way to record time is durationSeconds. You can also send a human duration string like "1h30m" or "1:30".

curl https://hoursmith.app/api/v1/time-entries \
  -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "pr_...",
    "entryDate": "2026-06-11",
    "durationSeconds": 5400,
    "note": "Homepage layout",
    "billable": true
  }'
await fetch('https://hoursmith.app/api/v1/time-entries', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.HOURSMITH_API_TOKEN}`,
    'Idempotency-Key': crypto.randomUUID(),
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    projectId: 'pr_...',
    entryDate: '2026-06-11',
    duration: '1h30m',
    note: 'Homepage layout',
  }),
});

Check the running timer

curl "https://hoursmith.app/api/v1/time-entries?running=true&limit=1" \
  -H "Authorization: Bearer $TOKEN"

Pull a month of time for a project

curl "https://hoursmith.app/api/v1/time-entries?projectId=pr_...&entryDateFrom=2026-06-01&entryDateTo=2026-06-30&sort=-entryDate&limit=200" \
  -H "Authorization: Bearer $TOKEN"

Then page with the nextCursor until it's null.

Find unpaid invoices

Invoices are read-only over the API. List the sent ones and check each invoice's paymentStatus field (unpaid, partially_paid, paid, refunded):

curl "https://hoursmith.app/api/v1/invoices?status=sent&sort=-issueDate" \
  -H "Authorization: Bearer $TOKEN"
const res = await fetch('https://hoursmith.app/api/v1/invoices?status=sent', {
  headers: { Authorization: `Bearer ${token}` },
});
const { data } = await res.json();
const unpaid = data.filter((inv) => inv.paymentStatus !== 'paid');

Creating and sending invoices stays in the app (or happens automatically as you bill tracked time). The API gives you read access to the results so you can sync them into your own reporting.

Tips for robust integrations

  • Generate one Idempotency-Key per logical write and reuse it on retries.
  • Handle 429 with Retry-After, and 409 for locked records.
  • Store ids you create (client, project) so later calls can reference them.
Was this page helpful?

On this page