# Re-bids, reminders & My day

These endpoints do what the buttons on the Re-bids page, My day and the Touch points window do. Each one runs the app's own action as the person who created the API key, so the same rules apply (a member who only sees their own jobs can only act on their own re-bids, for example) and the change shows in the timeline under their name.

**Nothing here emails or texts a customer.** Reminders and "remind me" follow-ups email *your* teammate when they come due, the same as in the app.

!!! note
    Partner keys that act for several workspaces must also send `firm_id` (query string, or JSON body on writes).

Errors are `{"error": "...", "message": "..."}`. Another workspace's id is a `404`. A body field the endpoint doesn't take is a `400` naming it.

## Re-bid actions

A re-bid is one property x one service coming due again (read them with [`GET /v1/rebids`](customers-and-sites.md)). It is identified by the pair `key` + `cycle_id` from that list. `key` can hold an address, so it always travels in the JSON body, never in the URL.

### Create re-bid jobs

`POST /v1/rebids/create-jobs`

**Permission:** Write jobs

Creates the re-bid job for each item, exactly like *Create re-bid* on the page (the job lands in your pipeline with the property, customer and service filled in). An item that already has its job returns it. Up to 100 items per call; one bad item never blocks the rest.

```bash
curl -X POST "https://trutec.ai/api/v1/rebids/create-jobs" \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"items": [{"key": "loc:812", "cycle_id": 3}, {"key": "loc:977", "cycle_id": 3}]}'
```

```json
{
  "data": {
    "created": 2, "existing": 0, "failed": 0,
    "items": [
      {"key": "loc:812", "cycle_id": 3, "rebid_job_id": 70412, "rebid_job_name": "Sealcoating re-bid - Oak Hills Plaza"},
      {"key": "loc:977", "cycle_id": 3, "rebid_job_id": 70413, "rebid_job_name": "Sealcoating re-bid - Ridgeview HOA"}
    ]
  }
}
```

`201` when at least one job was created, else `200`. **Errors:** `404` with `items` listing the pairs that aren't re-bids in this workspace; `403` when jobs in this workspace come from a connected system and can't be created in TruTec.

### Snooze, decline or reset a re-bid

| Endpoint | Body | What it does |
|---|---|---|
| `POST /v1/rebids/snooze` | `key`, `cycle_id`, `until` (YYYY-MM-DD) | Hide it until a date after today (at most two years out). |
| `POST /v1/rebids/not-doing` | `key`, `cycle_id`, `reason`, `note` | Take it off the list. `reason` is `sold`, `self` (they do it themselves), `competitor` or `other` (needs a `note`). |
| `POST /v1/rebids/reset` | `key`, `cycle_id` | Undo a snooze or "not doing". |

**Permission:** Write jobs. Each returns `{"data": {re-bid}}` with the new `status`, `snooze_until` and `not_doing_reason`.

### Schedule a re-bid follow-up

`POST /v1/rebids/follow-up`

**Permission:** Write jobs

A company follow-up about the re-bid (the property needs a company). It shows in the assignee's My day and they are reminded when it's due.

| Name | Type | Required | Description |
|---|---|---|---|
| `key`, `cycle_id` | | Yes | The re-bid. |
| `due` | string | Yes | YYYY-MM-DD. |
| `title` | string | No | Default *Call about &lt;service&gt; re-bid - &lt;property&gt;*. |
| `assigned_to_user_id` | integer | No | Default: the property's salesperson, else the key's user. |
| `task_type` | string | No | `call` (default), `email`, `meeting`, `site_visit` or `follow_up`. |

Returns `201` with `{"data": {"rebid": {...}, "task": {company follow-up}}}`.

### Add past work

`POST /v1/rebids/history`

**Permission:** Write jobs

Record work done at a site that isn't in TruTec as a job ("we sealcoated it in June 2023"), so its re-bid comes due on time.

| Name | Type | Required | Description |
|---|---|---|---|
| `location_id` | integer | Yes | The site. |
| `cycle_id` | integer | One of | The service, from `GET /v1/rebid-cycles`. |
| `new_service` | string | One of | Or a service name to add (an existing one with that name is reused). |
| `new_service_every_years` | integer | No | How often the new service comes due. Default 2. |
| `done_on` | string | Yes | YYYY-MM-DD. |
| `amount` | number | No | What it cost, in dollars. |
| `note` | string | No | |

Returns `201` with `{"data": {"id", "location_id", "cycle_id", "done_on", "amount", "note", "source": "manual", ...}}`.

### Remove past work

`DELETE /v1/rebids/history/{record_id}`

**Permission:** Write jobs + Delete records

Only work added by hand can be removed (`409` otherwise: work from a job follows the job). Returns `204`.

## Reminders

Contract-renewal and maintenance check-in reminders on customers (set from the customer's renewal date and check-in interval), plus other office reminders. When one comes due, the assignee gets an email and it shows in their My day.

### The reminder object

| Field | Type | Description |
|---|---|---|
| `id` | integer | TruTec id. |
| `title`, `description` | string | |
| `reminder_type` | string | `contract_renewal`, `maintenance_checkin` or `follow_up`. |
| `status` | string | `pending`, `sent` (emailed, not handled yet), `done` or `dismissed`. |
| `client_account_id`, `contact_id`, `job_id`, `lead_id` | integer or null | What it is about. |
| `repeat_every_days` | integer or null | null = one-off. |
| `due_at` | string or null | When it emails the assignee next (UTC). |
| `last_emailed_at` | string or null | |
| `assigned_to_user_id`, `assigned_to` | | Who gets it. |
| `created_at` | string | UTC. |

### List reminders

`GET /v1/reminders`

**Permission:** Read jobs

Soonest due first. Filters: `status` (`open` = pending or sent, the default; `pending`, `sent`, `done`, `dismissed`, `all`), `reminder_type`, `client_account_id`, `contact_id`, `job_id`, `assigned_to_user_id`, `due_before`, `due_after` (ISO 8601), `limit`, `offset`.

### Update a reminder

`PATCH /v1/reminders/{reminder_id}`

**Permission:** Write jobs

Only the fields sent change.

| Name | Type | Description |
|---|---|---|
| `title`, `description` | string | |
| `due` | string | Local `YYYY-MM-DDTHH:MM`, or a date (9:00 AM), read in `timezone`. Reschedules it. |
| `snooze` | string | Instead of `due`: `1h`, `tomorrow` (8 AM) or `next_week` (Monday 8 AM). |
| `timezone` | string | IANA zone for `due` / `snooze`. Default the workspace's. |
| `repeat_every` + `repeat_unit` | integer + string | Repeat every N `day`s, `week`s or `month`s. `0` stops repeating. |
| `assigned_to_user_id` | integer or null | |

### Complete or dismiss a reminder

`POST /v1/reminders/{reminder_id}/complete` with optional `notes` (logged on the customer or job). A repeating reminder stays open for its next round. `409` when it is already done or dismissed.

`POST /v1/reminders/{reminder_id}/dismiss` stops it: it won't email again.

**Permission:** Write jobs. Both return `{"data": {reminder}}`.

## Update many follow-ups at once

`POST /v1/follow-ups/bulk`

**Permission:** Write jobs

My day's *select many*: mark done, snooze or reassign job follow-ups, company follow-ups and reminders in one call.

| Name | Type | Required | Description |
|---|---|---|---|
| `action` | string | Yes | `done`, `snooze` or `reassign`. |
| `task_ids` | integer[] | One of | Job follow-ups (`/v1/tasks`). |
| `account_task_ids` | integer[] | One of | Company follow-ups (`/v1/account-tasks`). |
| `reminder_ids` | integer[] | One of | Reminders. |
| `snooze` | string | For snooze | `1h`, `tomorrow` or `next_week`. |
| `assigned_to_user_id` | integer | For reassign | An office user. |

```json
{"data": {"action": "snooze", "changed": 7, "skipped": 1}}
```

Rows the key's user may not act on, or already finished, are skipped and counted. Every id must be in this workspace (`404` lists the ones that aren't).

## "Remind me" and birthday follow-ups

### Remind me about a customer or a person

`POST /v1/client-accounts/{account_id}/remind-me`
`POST /v1/contacts/{contact_id}/remind-me`

**Permission:** Write jobs

The Touch points window's *Remind me*: a company follow-up for the key's user (from a person, it goes on their company and names them; the person must be linked to a company).

| Name | Type | Required | Description |
|---|---|---|---|
| `due_date` | string | Yes | YYYY-MM-DD. |
| `due_time` | string | No | 24-hour `HH:MM`. Default `09:00`. |
| `title` | string | No | Default *Call &lt;name&gt;*. |
| `repeat` | string | No | `none` (default), `weekly`, `monthly` or `yearly`. |
| `email_me` | string | No | `none` (default), `that_day` or `day_before`: emails the key's user. |
| `task_type` | string | No | `call` (default), `email` or `follow_up`. |
| `note` | string | No | |

Returns `201` with `{"data": {company follow-up}}`.

### Birthday reminder

`POST /v1/contacts/{contact_id}/birthday-reminder`

**Permission:** Write jobs

A yearly call follow-up on the person's next birthday (9 AM, emailed that day). Save their birthday first (`PATCH /v1/contacts/{contact_id}`). Safe to repeat: an open one is moved to the right date. Returns `201` with `"created": true` the first time, `200` after.
