---
title: "openemail.follow_ups"
description: "Every method in this namespace: its signature, its parameters, what it returns and an example."
url: "https://openemail.uk/docs/python/reference/follow-ups"
area: "Python"
category: "Reference"
---

# openemail.follow_ups

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.

### `follow_ups.list()`

List reminders

```python
def list(
    *,
    status: FollowUpStatus | None = None,
    thread_id: str | None = None,
    limit: int | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> builtins.list[FollowUpResource]
```

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.

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` (`FollowUpStatus`): Only reminders in this state: `waiting`, `answered`, `due` or `cancelled`, one of `FOLLOW_UP_STATUSES`.
- `thread_id` (`str`): Only the reminders on this thread.
- `limit` (`int`): How many to return, newest first, from 1 to 200. 100 when left out.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `OpenEmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

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

**Example**

```python
from openemail import openemail

waiting = openemail.follow_ups.list(status='waiting')

for reminder in waiting:
    print(reminder['subject'], reminder['remindAt'])
```

**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); Ruby [`follow_ups.list`](https://openemail.uk/docs/ruby/reference/follow-ups#list); PHP [`followUps->list`](https://openemail.uk/docs/php/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).

### `follow_ups.set()`

Set a reminder on a thread

```python
def set(
    body: FollowUpSet,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> FollowUpResource
```

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 `datetime` or an ISO 8601 string with an offset, and the SDK sends a `datetime` as a UTC ISO 8601 string. To set one as you send, pass `followUpAt` to `emails.send` instead.

Scopes: `threads:write`.

**Parameters**

- `body['threadId']` (`str`, required): The thread to be reminded about, as `threads.list` returns it.
- `body['remindAt']` (`datetime | str`, required): When the thread comes back if nobody replied: a future instant, at most 365 days out.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `OpenEmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`FollowUpResource`, the reminder with `status` set to `waiting`, in the shape `list` returns: `object` set to `follow_up`, `id`, `threadId`, `messageId`, `emailId`, `subject`, `remindAt`, `status`, `answeredAt`, `firedAt` and `createdAt`.

**Example**

```python
from datetime import datetime, timedelta, timezone

from openemail import openemail

remind_at = datetime.now(timezone.utc) + timedelta(days=3)

reminder = openemail.follow_ups.set({'threadId': 'thr_8f2c41d0a3b94e6f', 'remindAt': remind_at})

print(reminder['id'], reminder['status'], reminder['remindAt'])
```

**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 in `settings`.
- The SDK retries this call after a network failure, which is safe because setting the same time twice leaves one reminder.
- A naive `datetime` is read in the local zone of the machine running the SDK, so give it a `tzinfo`.

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); Ruby [`follow_ups.set`](https://openemail.uk/docs/ruby/reference/follow-ups#set); PHP [`followUps->set`](https://openemail.uk/docs/php/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).

### `follow_ups.cancel()`

Cancel a reminder

```python
def cancel(
    id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> FollowUpResource
```

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` (`str`, required): The id of the reminder, `fup_` and 24 hex characters, as `list` returns it.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `OpenEmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

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

**Example**

```python
from openemail import openemail

cancelled = openemail.follow_ups.cancel('fup_4c1b257a9e3d6f8025b7c1d4')

print(cancelled['status'], cancelled['remindAt'])
```

**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); Ruby [`follow_ups.cancel`](https://openemail.uk/docs/ruby/reference/follow-ups#cancel); PHP [`followUps->cancel`](https://openemail.uk/docs/php/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).
