diff --git a/README.md b/README.md index 8ef811c..1f38c4d 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,12 @@ Working example at [node.timetrackerapi.com](http://node.timetrackerapi.com). | `GET /v1/customer/:id` | yes (`authKey`) | Single customer lookup. Master key sees all; non-master only sees customers in its own company. | | `GET /v1/customer/bycompany/:id` | yes (`authKey`) | Customers in a company (paginated). Master sees any; non-master only its own. Query params: `limit` (default 100, max 500), `offset` (default 0). Archived customers (`custArch = true`) are filtered out. | | `POST /v1/customer` | yes (`authKey`) | Create a customer. Master key may target any `custCompId`; non-master keys can only create within their own company (and `custCompId` defaults to that). Returns 201 + the created customer. | +| `GET /v1/customer/search` | yes (`authKey`) | Case-insensitive substring search across `custCompanyName`, `custFName`, `custLName`. Query params: `q` (2-char minimum), `companyId` (master-only — non-master keys are auto-scoped and a mismatched `companyId` returns 403), `limit` (default 100, max 500), `offset` (default 0). | +| `GET /v1/customer/export.csv` | yes (`authKey`) | CSV export of customers in a company. Master keys must supply `companyId`; non-master keys are auto-scoped. `limit` (default 5000, max 5000). Cells starting with `=`, `+`, `-`, `@`, tab, or CR are prefixed with a single quote to defuse OWASP CSV-formula injection on spreadsheet-app open. | | `POST /v1/timeentry` | yes (`authKey`) | Create a time entry. Body: `teCustId` (required), `teStartedAt` (required, ISO 8601), `teEndedAt` (optional — in-flight entries allowed), `teDescription`, `teBillable` (default true). `teMinutes` is computed server-side on close. | | `GET /v1/timeentry/:id` | yes (`authKey`) | Single time entry lookup. Company-scoped. Archived (soft-deleted) entries return 404. | | `GET /v1/timeentry/bycompany/:id` | yes (`authKey`) | List time entries for a company. Query params: `customerId` (filter), `from` / `to` (ISO 8601 date range on `teStartedAt`), `limit` (default 100, max 500). Ordered most-recent first. | +| `GET /v1/timeentry/export.csv` | yes (`authKey`) | CSV export of time entries. Same auth contract + CSV-injection guard as `/v1/customer/export.csv`. Query params: `companyId` (master-only), `customerId` (filter), `from` / `to` (ISO 8601), `limit` (default 5000, max 5000). | | `PATCH /v1/timeentry/:id` | yes (`authKey`) | Partial update. Updatable: `teDescription`, `teStartedAt`, `teEndedAt`, `teBillable`. `teMinutes` is recomputed on bound change. | | `DELETE /v1/timeentry/:id` | yes (`authKey`) | Soft-delete (sets `teArch = true`). Entries are never physically removed via the API. | | `* /v1/worker/*` | yes (`authKey`) | Full CRUD for Workers (`workerId`, `workerFName`, `workerLName`, `workerTitle`, `workerDefaultBillType`, `workerCompId`, `workerArch`). Direct company scoping via `workerCompId`. Endpoints: `POST /v1/worker`, `GET /v1/worker/:id`, `GET /v1/worker/bycompany/:id`, `PATCH /v1/worker/:id`, `DELETE /v1/worker/:id`. |