Перейти к документации
API

Обновление домена

Задаёт, перепроверяет или удаляет собственный tracking-домен и собственный домен для файлов — две вещи в домене, которые этот API может изменить.

PATCHapi.openemail.uk/domains/{id}

Выполняет настоящий запрос в вашем рабочем пространстве, с вашим собственным ключом.

PATCH /domains/{id}

Задаёт, перепроверяет или удаляет собственный tracking-домен и собственный домен для файлов — две вещи в домене, которые этот API может изменить.

Запрос

У домена может быть один собственный tracking-домен и один собственный домен для файлов, каждый — выбранный вами поддомен, например links.acme.com и files.acme.com, как только домен верифицирован или его TXT-запись _openemail-challenge опубликована. Принимать почту он при этом ещё не обязан. Установка такого имени готовит адрес исключительно для него, о чём сообщает target, а record — это CNAME-запись, направляющая имя на него. Как только проверка пройдена, отслеживаемые ссылки и пиксель открытия в новых письмах с домена используют https://links.acme.com/t/..., а ссылки на скачивание отправленных с него файлов — https://files.acme.com/f/... вместо хоста по умолчанию.

Параметры

trackingHoststring | null
Поддомен для отслеживаемых ссылок и пикселя открытия, не длиннее 512 символов. Он обрезается по краям и приводится к нижнему регистру, а ведущий `https://` или `http://`, путь и точка в конце удаляются перед проверкой. Новое значение заменяет текущий tracking-домен, текущее значение запускает проверку заново, `null` или пустая строка удаляют его, а отсутствие поля оставляет его как есть.
storageHoststring | null
Поддомен для ссылок на скачивание файлов, очищаемый так же и ограниченный теми же 512 символами. Новое значение заменяет текущий домен для файлов, текущее значение запускает проверку заново, `null` или пустая строка удаляют его, а отсутствие поля оставляет его как есть.

Тело строго относится к ключам и свободно — к их количеству. Любой ключ, кроме trackingHost и storageHost, даёт 422 unknown_parameter, а тело, не содержащее ни одного из них, ничего не делает и отвечает 200 с доменом в его нынешнем виде. Оба можно передать в одном вызове, и применяются они по порядку, сначала trackingHost: отклонённый trackingHost останавливает вызов до того, как будет затронут storageHost, а отклонённый storageHost оставляет уже сделанное изменение trackingHost в силе. Отправляйте их по отдельности, когда любое из них должно применяться самостоятельно.

Настройка tracking-домена и домена для файлов

Требуется domains:write. Каждый хост проверяется, сохраняется и проверяется в том же вызове, поэтому ответ уже несёт результат этой первой проверки. Тело ответа такое же, как у GET /domains/{id}.

curl
curl -X PATCH "$OE/domains/b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f" -H "$AUTH" -H "Content-Type: application/json" \  -d '{ "trackingHost": "links.acme.com", "storageHost": "files.acme.com" }'
Ответ
{  "object": "domain",  "id": "b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f",  "domain": "acme.com",  "receiving": {    "verified": true,    "verifiedAt": "2026-08-14T10:02:00.000Z",    "catchAll": false,    "lastCheckedAt": "2026-08-29T06:00:00.000Z",    "error": null  },  "sending": {    "status": "verified",    "canSend": true,    "checkedAt": "2026-08-29T06:00:00.000Z",    "error": null,    "note": "Mail from this domain is signed and can be sent."  },  "tracking": {    "host": "links.acme.com",    "status": "pending",    "active": false,    "target": "oelinks3f9a1c7e2b8d4a60.edge.openemail.uk",    "record": { "type": "CNAME", "name": "links.acme.com", "value": "oelinks3f9a1c7e2b8d4a60.edge.openemail.uk" },    "checkedAt": "2026-08-29T06:05:12.000Z",    "verifiedAt": null,    "error": "links.acme.com does not resolve yet. Add a CNAME record named links.acme.com with the value oelinks3f9a1c7e2b8d4a60.edge.openemail.uk, then check again."  },  "storage": {    "host": "files.acme.com",    "status": "pending",    "active": false,    "target": "oefiles81c40d6b2f7e9a35.edge.openemail.uk",    "record": { "type": "CNAME", "name": "files.acme.com", "value": "oefiles81c40d6b2f7e9a35.edge.openemail.uk" },    "checkedAt": "2026-08-29T06:05:12.000Z",    "verifiedAt": null,    "error": "files.acme.com does not resolve yet. Add a CNAME record named files.acme.com with the value oefiles81c40d6b2f7e9a35.edge.openemail.uk, then check again."  },  "addresses": [    { "address": "[email protected]", "enabled": true }  ],  "createdAt": "2026-08-14T09:55:11.000Z"}

Опубликуйте tracking.record и storage.record у своего DNS-провайдера как обычные CNAME, с выключенным проксированием. Проверка резолвит каждое имя, затем запрашивает у https://links.acme.com/t/v/<nonce> или https://files.acme.com/f/v/<nonce> ответ, подписанный OpenEmail. Редирект проваливает проверку, как может провалить её и прокси перед именем.

Как только запись начинает резолвиться, проверка может сообщить, что имя указывает на OpenEmail и ждёт включения. Это выпускается его HTTPS-сертификат: он выпускается на нашей стороне, ничего от вас не требует и может занять некоторое время. Когда это закончится, следующая успешная проверка установит status в active.

Если адрес не удалось подготовить во время вызова, record равен null, target — пустая строка, а error сообщает, что подготовка идёт. Она завершается за несколько минут без повторного вызова, поэтому просто прочитайте домен ещё раз через GET /domains/{id}, чтобы получить запись.

Эти два имени независимы. Вызов с одним полем оставляет другой объект ровно таким, каким он был, поэтому более поздняя настройка файлов никогда не потревожит уже работающий tracking-домен.

Перепроверка или удаление

Отправьте хост, который у домена уже есть, чтобы запустить проверку сейчас, а не ждать следующей по расписанию. Если последняя проверка — по расписанию или нет — была меньше 30 секунд назад, вызов возвращает сохранённое состояние без изменений. Отправьте null в поле, чтобы удалить соответствующее имя, и опустите другое поле, чтобы сохранить имя, которое в нём хранится.

curl
curl -X PATCH "$OE/domains/b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f" -H "$AUTH" -H "Content-Type: application/json" \  -d '{ "trackingHost": null }'
tracking, после удаления
{  "host": null,  "status": "none",  "active": false,  "target": "",  "record": null,  "checkedAt": null,  "verifiedAt": null,  "error": null}

Ссылки в уже отправленных письмах сохраняют хост, с которым они ушли, и это касается ссылки на скачивание файла так же, как и отслеживаемой ссылки. После удаления или изменения имени такие ссылки продолжают работать до тех пор, пока старая CNAME-запись остаётся на месте. Повторная настройка имени может дать ему другой record, поэтому публикуйте тот, о котором сообщает ответ.

Объект tracking

hoststring | null
Tracking-домен или null, если у домена его нет.
status'none' | 'pending' | 'active' | 'failed'
`none` означает, что tracking-домен не задан. `pending` — что он задан и ещё ни разу не прошёл проверку. `active` — что новые письма используют его. `failed` — что он проходил проверку раньше, а затем вышел из употребления.
activeboolean
True ровно тогда, когда `status` равен `active`, то есть когда отслеживаемые ссылки и пиксель открытия в новых письмах с домена используют этот хост.
targetstring
Адрес, на который указывает CNAME-запись, подготовленный исключительно для этого tracking-домена. Это пустая строка, пока `host` равен null и пока адрес для нового хоста ещё готовится.
record{ type: 'CNAME'; name: string; value: string } | null
Запись, которую нужно опубликовать: её имя — `host`, значение — `target`. Null, когда tracking-домена нет и пока адрес для нового хоста ещё готовится.
checkedAtstring | null
Когда хост проверялся в последний раз, ISO-8601. Null до первой проверки.
verifiedAtstring | null
Когда проверка в последний раз была успешной, ISO-8601. Null для хоста, который ни разу её не прошёл.
errorstring | null
Что обнаружила последняя проверка, словами, по которым владелец домена может действовать. Null, когда последняя проверка прошла успешно или ни одной ещё не было. Хост, проваливший одну-две проверки, всё ещё `active` и несёт причину здесь.

Объект storage

Домен для файлов отчитывается в storage, поле в поле так же, как tracking. Различается только назначение имени: active там означает, что ссылки на скачивание файлов, отправленных с домена, указывают на него.

hoststring | null
Домен для файлов или null, если у домена его нет.
status'none' | 'pending' | 'active' | 'failed'
`none` означает, что домен для файлов не задан. `pending` — что он задан и ещё ни разу не прошёл проверку. `active` — что новые письма используют его. `failed` — что он проходил проверку раньше, а затем вышел из употребления.
activeboolean
True ровно тогда, когда `status` равен `active`, то есть когда ссылки на скачивание файлов, отправленных с домена, используют этот хост.
targetstring
Адрес, на который указывает CNAME-запись, подготовленный исключительно для этого домена для файлов. Это пустая строка, пока `host` равен null и пока адрес для нового хоста ещё готовится.
record{ type: 'CNAME'; name: string; value: string } | null
Запись, которую нужно опубликовать: её имя — `host`, значение — `target`. Null, когда домена для файлов нет и пока адрес для нового хоста ещё готовится.
checkedAtstring | null
Когда хост проверялся в последний раз, ISO-8601. Null до первой проверки.
verifiedAtstring | null
Когда проверка в последний раз была успешной, ISO-8601. Null для хоста, который ни разу её не прошёл.
errorstring | null
Что обнаружила последняя проверка, словами, по которым владелец домена может действовать. Null, когда последняя проверка прошла успешно или ни одной ещё не было. Хост, проваливший одну-две проверки, всё ещё `active` и несёт причину здесь.

Как проверяется хост

Оба имени проверяются по одному и тому же расписанию, и каждое проверяется самостоятельно.

  • Хост, ещё не прошедший проверку, проверяется каждые 2 минуты в первый час, каждые 10 минут в первые сутки, раз в час в первую неделю и каждые 6 часов после этого.
  • Активный хост проверяется каждые 10 минут, а неудачная проверка по нему повторяется через 1 минуту, а затем через 2.
  • Активный хост перестаёт использоваться после трёх неудачных проверок подряд или как только его последней успешной проверке больше 2 часов. Новые письма тогда возвращаются к хосту по умолчанию, а status читается как failed, пока проверка снова не пройдёт. Проверки продолжаются, каждый раз всё реже, но не реже раза в час.

Tracking-домен обслуживает только пути трекинга, а домен для файлов — только пути скачивания, и каждый отвечает только за письма, отправленные владеющим им рабочим пространством.

Ошибки

СтатусtypecodeКогда
400invalid_request_errormalformed_jsonТело не является корректным JSON.
403permission_errorinsufficient_scopeУ ключа нет domains:write.
404not_found_errorresource_not_foundВ этом рабочем пространстве нет домена с таким id.
409conflict_errordomain_not_verifiedНовый хост был отправлен, пока receiving.verified равен false, а TXT-запись домена _openemail-challenge ещё не опубликована. param — поле, в котором он пришёл: trackingHost или storageHost.
409conflict_errortracking_host_in_useДругой домен уже использует этот хост как свой tracking-домен, хост уже используется как домен для файлов, либо tracking-доменом этого домена управляет другой сервер OpenEmail. param равен trackingHost.
409conflict_errorstorage_host_in_useТе же три случая для домена для файлов: другой домен уже использует этот хост как свой домен для файлов, хост уже используется как tracking-домен, либо доменом для файлов здесь управляет другой сервер OpenEmail. param равен storageHost.
422validation_errorinvalid_tracking_hostХост не является корректным именем узла или не разрешён: он должен быть строгим поддоменом домена и не может быть хостом обратного пути bounce.<domain>, именем, принадлежащим OpenEmail, или доменом, настроенным на приём почты. param равен trackingHost.
422validation_errorinvalid_storage_hostТе же правила, отказ по домену для файлов. param равен storageHost.
422validation_errorunknown_parameterКлюч тела, отличный от trackingHost и storageHost.
422validation_errorinvalid_parameterТело не является объектом JSON, либо присутствующее поле не является ни строкой, ни null, либо превышает 512 символов. Тело, не содержащее ни одного из полей, — не ошибка: оно ничего не меняет и возвращается с 200.
422validation_errorcapability_unsupportedКлюч сужен до отдельных адресов, а не до всего этого домена, тогда как оба имени действуют на каждый адрес домена. Ключ, у которого домен указан в domainAllowlist, может их задать. param равен domainAllowlist.