Skip to the documentation
API

Suppressions

Every operation in this group: what it accepts, what it returns and the errors it can answer with.

Operations

The addresses this workspace will not send to: hard bounces and complaints, recorded as they happen, and any address somebody blocks by hand. A send to one is refused for that recipient before anything leaves. A hard bounce stays for good; a complaint or a manual entry can be removed. Reading needs settings:read and changing needs settings:write, the scopes the Blocked addresses screen in Settings is gated on.

GET/suppressions

List suppressed addresses

Scopessettings:readReads

The addresses this workspace will not send to, newest first: every address that bounced hard, complained, or was added by hand. It is the Blocked addresses screen in Settings. A send to a suppressed address is refused for that recipient before anything leaves, and a message whose recipients are all suppressed fails outright.

The list belongs to the whole workspace, so a key limited to particular addresses or domains reads all of it. A row names the recipient and never which of your addresses sent to it.

Requires the settings:read scope.

Query parameters

qstring

Searches the address, the reason and the detail. Words match loosely, and a close spelling is tried when nothing matches exactly.

Up to 320 characters
reasonstring

Keeps one kind.

One of"bounce""complaint""manual"
limitinteger

Rows per page, 1 to 100.

At least 1At most 100Default25
cursorstring

The previous page's nextCursor, passed back as it came. It is opaque: it holds where the last row sat in this list's order, so a row deleted or edited between pages never breaks the walk, and the next page starts at the first row that sorts after it. A value this list did not hand out is a 400 invalid_cursor.

Returns

A page of the suppression list, newest first.

Errors

The errors every operation can return400401403404422429500Error catalog

Also available in

TypeScript
suppressions.list()suppressions.listAll()suppressions.iterate()
Python
suppressions.list()suppressions.list_all()suppressions.iterate()
Ruby
suppressions.listsuppressions.list_allsuppressions.iterate
PHP
suppressions->listsuppressions->listAllsuppressions->iterate
Go
Suppressions.ListSuppressions.ListAllSuppressions.Iterate
Java
suppressions().listsuppressions().listAllsuppressions().iterate
C#
Suppressions.ListAsyncSuppressions.ListAllAsyncSuppressions.IterateAsync
CLI
openemail suppressions list
MCP
listSuppressions

POST/suppressions

Add a suppressed address

Scopessettings:writeChanges data

Puts an address on the list by hand, with reason: "manual", so no address in the workspace sends to it until it is removed. Adding one that is already there changes nothing and answers 200 with the row it already holds, whatever its reason. A new entry fires suppression.added.

The list stops mail from every address in the workspace, so a key limited to particular addresses or domains, and an app connected by anybody but the owner, cannot change it.

Requires the settings:write scope.

Request body

emailstringRequired

The address to stop sending to. Trimmed and lower-cased on the way in.

Up to 320 charactersFormatemail

Returns

It was already on the list. The row that was there, unchanged.

Added. Nothing is sent to the address from here on.

Errors

422

invalid_parameter for an address that is not one, or capability_unsupported for a key limited to particular addresses or domains.

The errors every operation can return400401403404429500Error catalog

Also available in

TypeScript
suppressions.add()
Python
suppressions.add()
Ruby
suppressions.add
PHP
suppressions->add
Go
Suppressions.Add
Java
suppressions().add
C#
Suppressions.AddAsync
CLI
openemail suppressions add
MCP
addSuppression

GET/suppressions/{id}

Retrieve a suppressed address

Scopessettings:readReads

One row of the suppression list.

Requires the settings:read scope.

Path parameters

idstringRequired

The id from GET /suppressions.

Returns

The row.

Errors

The errors every operation can return400401403404422429500Error catalog

Also available in

TypeScript
suppressions.get()
Python
suppressions.get()
Ruby
suppressions.get
PHP
suppressions->get
Go
Suppressions.Get
Java
suppressions().get
C#
Suppressions.GetAsync
CLI
openemail suppressions get
MCP
listSuppressions

DELETE/suppressions/{id}

Remove a suppressed address

Scopessettings:writeDeletes

Takes an address off the list, so mail may go to it again. It is Allow again on the Blocked addresses screen, and it fires suppression.removed. Only a complaint or a manual entry can be removed.

Requires the settings:write scope.

Path parameters

idstringRequired

The id from GET /suppressions.

Returns

200object

Removed. Mail may go to the address again.

objectstring
One of"suppression"
idstring
emailstring
deletedboolean
One oftrue

Errors

409

suppression_not_removable: the address bounced hard, so it stays. Check the address is right and send to the corrected one.

422

capability_unsupported for a key limited to particular addresses or domains.

The errors every operation can return400401403404429500Error catalog

Also available in

TypeScript
suppressions.remove()
Python
suppressions.remove()
Ruby
suppressions.remove
PHP
suppressions->remove
Go
Suppressions.Remove
Java
suppressions().remove
C#
Suppressions.RemoveAsync
CLI
openemail suppressions remove
MCP
removeSuppression

GET/suppressions/unsubscribes

List unsubscribes

Scopessettings:readReads

The people who asked this workspace for no more marketing mail, newest first. It is the Unsubscribed list on the Blocked addresses screen in Settings.

An unsubscribe belongs to the whole workspace and outlasts the contact: removing the person from an audience, deleting the contact or importing the address again never brings them back. Every broadcast and automation email skips them, and adding them to an audience records them there as unsubscribed. Mail people write to you, and the replies you send, still reach them, because only marketing mail stops. A hard block on every kind of mail is the suppression list, GET /suppressions.

Somebody stops being on this list only by their own hand: a sign-up they confirm from their inbox, or Subscribe again on the unsubscribe page. An unsubscribe recorded by hand with POST /suppressions/unsubscribes is the one kind DELETE takes back.

Requires the settings:read scope.

Query parameters

qstring

One whole address, matched exactly and without regard to case. Addresses here are stored encrypted, so a part of one finds nothing.

Up to 320 characters
sourcestring

Keeps one way of unsubscribing.

One of"link""one_click""manual""complaint""import"
limitinteger

Rows per page, 1 to 100.

At least 1At most 100Default25
cursorstring

The previous page's nextCursor, passed back as it came. It is opaque: it holds where the last row sat in this list's order, so a row deleted or edited between pages never breaks the walk, and the next page starts at the first row that sorts after it. A value this list did not hand out is a 400 invalid_cursor.

Returns

A page of the unsubscribe list, newest first.

Errors

The errors every operation can return400401403404422429500Error catalog

Also available in

TypeScript
suppressions.listUnsubscribes()
Python
suppressions.list_unsubscribes()
Ruby
suppressions.list_unsubscribes
PHP
suppressions->listUnsubscribes
Go
Suppressions.ListUnsubscribes
Java
suppressions().listUnsubscribes
C#
Suppressions.ListUnsubscribesAsync
CLI
openemail suppressions list-unsubscribes
MCP
listUnsubscribes

POST/suppressions/unsubscribes

Record an unsubscribe

Scopessettings:writeChanges data

Records that somebody asked to stop getting marketing mail, for when they asked by phone, in a reply or anywhere else, with source: "manual". Their contact, if there is one, is unsubscribed from every audience at once, the automations sending to them end, and contact.unsubscribed fires. Recording an address that is already on the list changes nothing and answers 200.

The list covers every address in the workspace, so a key limited to particular addresses or domains, and an app connected by anybody but the owner, cannot change it.

Requires the settings:write scope.

Request body

emailstringRequired

The address that asked for no more marketing mail. Trimmed and lower-cased on the way in.

Up to 320 charactersFormatemail

Returns

The address had already unsubscribed. The record that was there.

Recorded. No broadcast or automation email goes to the address from here on.

Errors

422

invalid_parameter for an address that is not one, or capability_unsupported for a key limited to particular addresses or domains.

The errors every operation can return400401403404429500Error catalog

Also available in

TypeScript
suppressions.addUnsubscribe()
Python
suppressions.add_unsubscribe()
Ruby
suppressions.add_unsubscribe
PHP
suppressions->addUnsubscribe
Go
Suppressions.AddUnsubscribe
Java
suppressions().addUnsubscribe
C#
Suppressions.AddUnsubscribeAsync
CLI
openemail suppressions add-unsubscribe
MCP
addUnsubscribe

DELETE/suppressions/unsubscribes/{email}

Take back a recorded unsubscribe

Scopessettings:writeDeletes

Takes back an unsubscribe the team recorded by hand, for one recorded by mistake. The audiences it unsubscribed are subscribed again, and contact.resubscribed fires. Every other source is refused with 409 unsubscribe_not_removable, because a person who unsubscribed decides alone whether to come back: through a sign-up form they confirm from their inbox, or Subscribe again on the unsubscribe page.

Requires the settings:write scope.

Path parameters

emailstringRequired

The address that unsubscribed, URL-encoded. Case does not matter.

Up to 320 characters

Returns

200object

Taken back. The audiences it unsubscribed are subscribed again.

objectstringRequired
One of"unsubscribe"
emailstringRequired
deletedbooleanRequired
One oftrue

Errors

409

unsubscribe_not_removable: the person unsubscribed themselves, complained, or left at another provider, so only they can subscribe again.

422

capability_unsupported for a key limited to particular addresses or domains.

The errors every operation can return400401403404429500Error catalog

Also available in

TypeScript
suppressions.removeUnsubscribe()
Python
suppressions.remove_unsubscribe()
Ruby
suppressions.remove_unsubscribe
PHP
suppressions->removeUnsubscribe
Go
Suppressions.RemoveUnsubscribe
Java
suppressions().removeUnsubscribe
C#
Suppressions.RemoveUnsubscribeAsync
CLI
openemail suppressions remove-unsubscribe
MCP
removeUnsubscribe

Objects

Suppressionobject

objectstring
One of"suppression"
idstring
emailstring

The recipient address, lower-cased. It is somebody you sent to, not one of your own.

reasonstring

bounce is a hard bounce and stays for good. complaint means the recipient marked a message as spam. manual means somebody added it.

One of"bounce""complaint""manual"
detailstring

What the bounce or complaint said, when it said anything.

Can be null
removableboolean

Whether DELETE /suppressions/{id} will take it off. False for a bounce.

createdAtstring
Formatdate-time

SuppressionListobject

objectstring
One of"list"
hasMoreboolean

True when another page follows. Pass nextCursor back as cursor to read it.

nextCursorstring

An opaque cursor for the next page, or null on the last page. Pass it back unchanged.

Can be null

Unsubscribeobject

objectstringRequired
One of"unsubscribe"
emailstringRequired

The address, lower-cased.

sourcestringRequired

link is the unsubscribe page, one_click the unsubscribe button a mail app shows from the List-Unsubscribe header, complaint a spam report, import an unsubscribe brought from another provider, and manual one the team recorded.

One of"link""one_click""manual""complaint""import"
broadcastIdstringRequired

The broadcast whose link or header they used, when it was one.

Can be null
automationIdstringRequired

The automation whose link or header they used, when it was one.

Can be null
removablebooleanRequired

Whether DELETE /suppressions/unsubscribes/{email} takes it back. True only for manual.

createdAtstringRequired

When they unsubscribed.

Formatdate-time

UnsubscribeListobject

objectstring
One of"list"
hasMoreboolean

True when another page follows. Pass nextCursor back as cursor to read it.

nextCursorstring

An opaque cursor for the next page, or null on the last page. Pass it back unchanged.

Can be null