Skip to the documentation
TypeScript

Labels

`labels.list`, `listAll`, `iterate`, `listColors`, `get`, `create`, `update` and `delete`.

Every method

usage.ts
const page = await nextmail.labels.list({ limit: 50 })const every = await nextmail.labels.listAll()const colors = await nextmail.labels.listColors() const created = await nextmail.labels.create({  name: 'Invoices',  color: { backgroundColor: 'gradient:sunset' },}) await nextmail.labels.update(created.id, { name: 'Invoices 2027' })await nextmail.labels.update(created.id, { color: { backgroundColor: '#3B82F6' } })await nextmail.labels.delete(created.id)

list resolves to one Page of labels sorted by name, and listAll and iterate walk every page. Each label carries its colour, threadCount and when it was created and last changed. listColors returns the palette the app offers, fourteen solids and seven gradients, as a plain array. type is always user. The id comes from the name the label was created with, so Invoices is USER_INVOICES, and it never changes.

A label belongs to the workspace, so a rename, a recolour or a delete changes it for every member and every key. threads.update puts labels on a conversation and takes them off, and threads.list({ folder: 'USER_INVOICES' }) lists every conversation carrying one.

Parameters: labels.create and labels.update

namestring
The label's display name, trimmed before it is measured, so the limit is 1 to 225 characters after trimming. Required on `create` and optional on `update`, where leaving it out keeps the name. Whitespace alone is a 422. A name another label already has, compared without case, is a 409 `label_name_taken`, and `create` refuses once the workspace holds 50 labels, with a 422 `label_limit_reached`.
colorLabelColorInput | null
Optional on both calls. Leaving it out on `update` keeps the stored colour, and `null` clears it. The body is strict, so a near-miss key such as `colour` is a 422 rather than a silent no-op.
color.backgroundColorstringrequired
A hex colour (`#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA`, stored upper-cased) or a gradient token: `gradient:sunset`, `gradient:ember`, `gradient:meadow`, `gradient:lagoon`, `gradient:aurora`, `gradient:berry` or `gradient:midnight`. An empty string means no colour, and anything else is a 422 `invalid_parameter`.
color.textColorstring
Accepted and ignored. The ink is worked out from `backgroundColor`, the same way the app does it.
aiInstructionsstring | null
What the label is for, in plain words and at most 500 characters, such as `invoices and receipts`. `null` on `update` clears it and stops the labelling.
aiEnabledboolean
Has AI add the label to arriving mail that fits `aiInstructions`. It needs instructions, or the call is a 422 `invalid_parameter`, and a paid plan, or it is a 403 `plan_required`. A workspace may have 10 such labels, and turning on one more is a 422 `ai_label_limit_reached`.

Response: Label

object'label'
Always the string `label`. `create` and `update` resolve with this same type, read back as it is stored.
idstring
The label's id, and what `get`, `update`, `delete` and `threads.update` take. It never changes, even after a rename.
namestring
What the user sees.
typestring
Always `user`. System labels are never served here, and a system id on `get` is a 404.
colorLabelColor | null
Null when the label has no colour.
color.backgroundColorstring
The stored colour: a hex value or a gradient token. `listColors` gives a gradient's two ends.
color.textColorstring
The ink the app draws on the colour, `#18181B` or `#FFFFFF`, worked out on the server rather than stored.
threadCountnumber
How many conversations carry the label now. For a key limited to particular addresses, only conversations delivered to them count.
createdAtstring | null
When the label was made, as ISO 8601, or null for a label made before these times were recorded.
updatedAtstring | null
The last rename or recolour, as ISO 8601, or null for a label made before these times were recorded.
aiInstructionsstring | null
What the label is for, as it was saved, or null when nothing was.
aiEnabledboolean
Whether AI adds the label to arriving mail that fits the instructions.

Response: LabelColorResource

kind'solid' | 'gradient'
Whether the swatch is one colour or a gradient.
namestring
The swatch name, such as `red` or `sunset`.
valuestring
What to send as `color.backgroundColor` to use this swatch.
solidstring
One hex for places a gradient cannot be drawn. The same as `value` on a solid.
fromstring | null
Where a gradient starts, drawn at 135 degrees. Null on a solid.
tostring | null
Where a gradient ends. Null on a solid.
textColorstring
The ink the app draws on this swatch.

Labels that AI applies

ai-labels.ts
const label = await nextmail.labels.create({  name: 'Receipts',  aiInstructions: 'invoices and receipts',  aiEnabled: true,}) const result = await nextmail.labels.test(label.id, {  aiInstructions: 'invoices, receipts and payment confirmations',}) console.log(`${result.matched.length} of ${result.examined} would get the label`)

With aiInstructions and aiEnabled, AI adds the label to arriving mail that fits what you wrote. It skips spam, the Bin, encrypted mail and muted threads, and it only ever adds the label. labels.test reads the newest 20 inbox threads and resolves the ones the label would catch, as matched, without labelling any of them.

labels.test spends one AI action of the caller, which the labelling of arriving mail never does, and takes aiInstructions to try wording you have not saved yet. It needs labels:write and threads:read.