---
title: "$client->followUps"
description: "Every method in this namespace: its signature, its parameters, what it returns and an example."
url: "https://openemail.uk/docs/php/reference/follow-ups"
area: "PHP"
category: "Reference"
---

# $client->followUps

Every method in this namespace: its signature, its parameters, what it returns and an example.

## Methods

Reminders on mail you sent: ask for a thread to come back to the top of the inbox if nobody replies by a time you choose, list the reminders still waiting and the ones that ended, and cancel one.

### `followUps->list`

List reminders

```php
list(
    ?string $status = null,
    ?string $threadId = null,
    ?int $limit = null,
    ?string $apiKey = null,
): array
```

Returns the reminders you set on mail you sent, newest first: the ones still waiting for a reply and the ones that ended. A reminder is `waiting` until somebody replies (`answered`), its time comes with no reply (`due`, and the thread is back at the top of the inbox, unread) or it is cancelled. `OpenEmail\Constants\FollowUpStatuses` holds the four states.

An API key lists the reminders of the workspace owner, and an app those of the person who connected it. A key or an app limited to particular addresses lists only reminders on threads delivered to them. They come back as one plain list with no paging, and `limit:` caps how many.

Scopes: `threads:read`.

**Parameters**

- `status` (`string`): Only reminders in this state: `waiting`, `answered`, `due` or `cancelled`, as in `OpenEmail\Constants\FollowUpStatuses`.
- `threadId` (`string`): Only the reminders on this thread.
- `limit` (`int`): How many to return, newest first, from 1 to 200. 100 when left out.
- `apiKey` (`string`): Overrides the client's API key for this call only.

**Returns**

A list of arrays, each with `object` set to `follow_up`, `id`, `threadId`, `messageId`, `emailId`, `subject`, `remindAt`, `status`, `answeredAt`, `firedAt` and `createdAt`. `threadId` is null until a scheduled message with a reminder goes out, `emailId` names the email when the reminder was set with `followUpAt`, `answeredAt` is null unless `answered` and `firedAt` is null unless `due`.

**Example**

```php
use OpenEmail\Constants\FollowUpStatuses;

$waiting = $client->followUps->list(status: FollowUpStatuses::WAITING);

foreach ($waiting as $reminder) {
    echo $reminder['subject'] ?? '(no subject)', ' comes back at ', $reminder['remindAt'], PHP_EOL;
}
```

**Notes**

- In `query:`, `is:waiting` finds the same conversations through `threads->list`: the ones with a reminder nobody has answered yet.
- Read only, so the SDK retries it after a network failure like any other read.

Also available in: API [`GET /follow-ups`](https://openemail.uk/docs/api/reference/threads#get-follow-ups); TypeScript [`followUps.list()`](https://openemail.uk/docs/sdk/reference/follow-ups#list); Python [`follow_ups.list()`](https://openemail.uk/docs/python/reference/follow-ups#list); Ruby [`follow_ups.list`](https://openemail.uk/docs/ruby/reference/follow-ups#list); Go [`FollowUps.List`](https://openemail.uk/docs/go/reference/follow-ups#list); Java [`followUps().list`](https://openemail.uk/docs/java/reference/follow-ups#list); C# [`FollowUps.ListAsync`](https://openemail.uk/docs/csharp/reference/follow-ups#list); CLI [`openemail follow-ups list`](https://openemail.uk/docs/cli/reference/follow-ups#follow-ups-list).

### `followUps->set`

Set a reminder on a thread

```php
set(array $body, ?string $apiKey = null): array
```

Asks to be reminded about a thread if nobody replies by `remindAt`. If a real reply arrives first, the reminder closes by itself. Otherwise, when the time comes, the thread returns to the top of the inbox, unread, with the built-in `FOLLOW_UP` label and a push to your phones. Automatic replies, delivery reports and your own sending address do not count as a reply.

A thread holds one waiting reminder per person, so setting another moves the time. `remindAt` takes a `DateTimeInterface` or an ISO 8601 string with an offset, and the SDK sends a `DateTimeInterface` as an ISO 8601 instant in UTC. To set one as you send, pass `followUpAt` to `emails->send` instead.

Scopes: `threads:write`.

**Parameters**

- `threadId` (`string`, required): The thread to be reminded about, as `threads->list` returns it.
- `remindAt` (`string|DateTimeInterface`, required): When the thread comes back if nobody replied: a future instant, at most 365 days out.
- `apiKey` (`string`): Overrides the client's API key for this call only.

**Returns**

An array, the reminder with `status` set to `waiting`: `object` set to `follow_up`, `id`, `threadId`, `messageId`, `emailId`, `subject`, `remindAt`, `status`, `answeredAt`, `firedAt` and `createdAt`.

**Example**

```php
$reminder = $client->followUps->set([
    'threadId' => 'CAHk7pQ2x9LmZ4-mail.example.com',
    'remindAt' => new \DateTimeImmutable('+3 days'),
]);

echo $reminder['id'], ' is ', $reminder['status'], ' until ', $reminder['remindAt'], PHP_EOL;
```

**Notes**

- A `remindAt` that is not in the future, or is more than 365 days out, is a 422 `invalid_follow_up`. A thread that does not exist, or one delivered to no address the key covers, is a 404.
- An API key sets the reminder for the workspace owner, and an app for the person who connected it. The push goes out unless that person turned `phoneFollowUps` off with `settings->update`.
- The SDK retries this call after a network failure, which is safe because setting the same time twice leaves one reminder.

Also available in: API [`POST /follow-ups`](https://openemail.uk/docs/api/reference/threads#post-follow-ups); TypeScript [`followUps.set()`](https://openemail.uk/docs/sdk/reference/follow-ups#set); Python [`follow_ups.set()`](https://openemail.uk/docs/python/reference/follow-ups#set); Ruby [`follow_ups.set`](https://openemail.uk/docs/ruby/reference/follow-ups#set); Go [`FollowUps.Set`](https://openemail.uk/docs/go/reference/follow-ups#set); Java [`followUps().set`](https://openemail.uk/docs/java/reference/follow-ups#set); C# [`FollowUps.SetAsync`](https://openemail.uk/docs/csharp/reference/follow-ups#set); CLI [`openemail follow-ups set`](https://openemail.uk/docs/cli/reference/follow-ups#follow-ups-set).

### `followUps->cancel`

Cancel a reminder

```php
cancel(string $id, ?string $apiKey = null): array
```

Cancels a waiting reminder, so the thread stays where it is when the time comes. A reminder that already ended is returned as it is, which is why the SDK retries this call. Only your own reminders can be cancelled.

Scopes: `threads:write`.

**Parameters**

- `id` (`string`, required): The id of the reminder, `fup_` and 24 hex characters, as `list` returns it.
- `apiKey` (`string`): Overrides the client's API key for this call only.

**Returns**

An array, the reminder as it is now: `status` is `cancelled` when it was waiting, and unchanged when it had already ended.

**Example**

```php
$cancelled = $client->followUps->cancel('fup_4c1b257a9e3d6f8025b7c1d4');

echo $cancelled['id'], ' is ', $cancelled['status'], ', it was due at ', $cancelled['remindAt'], PHP_EOL;
```

**Notes**

- An unknown id, and a reminder somebody else set, are each a 404. So is one on a thread delivered to no address the key covers.
- A cancelled reminder is kept, and `list` returns it with `status` set to `cancelled`.

Also available in: API [`DELETE /follow-ups/{id}`](https://openemail.uk/docs/api/reference/threads#delete-follow-ups-id); TypeScript [`followUps.cancel()`](https://openemail.uk/docs/sdk/reference/follow-ups#cancel); Python [`follow_ups.cancel()`](https://openemail.uk/docs/python/reference/follow-ups#cancel); Ruby [`follow_ups.cancel`](https://openemail.uk/docs/ruby/reference/follow-ups#cancel); Go [`FollowUps.Cancel`](https://openemail.uk/docs/go/reference/follow-ups#cancel); Java [`followUps().cancel`](https://openemail.uk/docs/java/reference/follow-ups#cancel); C# [`FollowUps.CancelAsync`](https://openemail.uk/docs/csharp/reference/follow-ups#cancel); CLI [`openemail follow-ups cancel`](https://openemail.uk/docs/cli/reference/follow-ups#follow-ups-cancel).
