Chuyển tới nội dung chính

Alerts and reports API

.

This page lists 21 endpoints (OpenAPI tag alerts). It is generated from openapi.json; see the REST API overview for authentication, CSRF and error conventions.

MethodPathOperation idNotes
GET/api/render/payloadrender_payload
GET/api/ws/{workspace}/alertslist
POST/api/ws/{workspace}/alertscreate
GET/api/ws/{workspace}/alerts/{id}detail
PUT/api/ws/{workspace}/alerts/{id}update
DELETE/api/ws/{workspace}/alerts/{id}remove
PUT/api/ws/{workspace}/alerts/{id}/activeset_active
POST/api/ws/{workspace}/alerts/{id}/bookmarkbookmark_addA bookmark is the CALLER's own, so it needs no alert:manage — a viewer may star what they can READ, which is now a permission that exists and is therefore ...
DELETE/api/ws/{workspace}/alerts/{id}/bookmarkbookmark_remove
PATCH/api/ws/{workspace}/alerts/{id}/folderset_folder
POST/api/ws/{workspace}/alerts/{id}/restorerestore
POST/api/ws/{workspace}/alerts/{id}/runrun_nowRun one schedule immediately (P5's "Run now").
GET/api/ws/{workspace}/alerts/{id}/runsruns
POST/api/ws/{workspace}/alerts/{id}/trashtrashMove to the trash (soft delete), so the list keeps a Restore path and the scheduler stops claiming it — deleted_at IS NULL is part of the claim predicate, ...
GET/api/ws/{workspace}/notifications/slackslack_getThe print page's ONE request.
PUT/api/ws/{workspace}/notifications/slackslack_put
DELETE/api/ws/{workspace}/notifications/slackslack_delete
GET/api/ws/{workspace}/notifications/smtpsmtp_get
PUT/api/ws/{workspace}/notifications/smtpsmtp_put
DELETE/api/ws/{workspace}/notifications/smtpsmtp_delete
POST/api/ws/{workspace}/notifications/smtp/testsmtp_testSend a probe message.

GET /api/render/payload​

Operation id: render_payload. Auth: Session cookie.

Response 200 (application/json): RenderPayload

FieldTypeRequiredDescription
kindstringyes
idstringyes
titlestringyes
cardsRenderCard[]yes
parametersobjectyesThe dashboard's parameter definitions, verbatim. The print page resolves them to filters with applyParamsToChart — the SAME module the interactive dashboard uses — and sends the result back to [run_cards].
StatusMeaning
200What is being rendered: the object's title, each card's saved spec and param mappings, and the dashboard's parameters. No rows — see POST /render/data
401No render token
404Token unknown, expired, or already used

GET /api/ws/{workspace}/alerts​

Operation id: list. Auth: Session cookie.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
typequeryScheduleTypenoNarrow to one tab. Omitted returns both.
trashedquerybooleannoShow the trash bin (soft-deleted rows) instead of the live list.

Response 200 (application/json): array of ScheduleSummaryDto

FieldTypeRequiredDescription
idstringyes
typeScheduleTypeyesWhat a schedule does: evaluate a query (alert), deliver a rendering of a saved object (report), or watch a Data API endpoint's traffic (dataapi_alert, migration 0128).
namestringyes
descriptionstringyes
activebooleanyes
crontabstringyes
timezonestringyes
next_run_atstring (date-time), nullableno
last_stateRunStateno
last_eval_atstring (date-time), nullableno
ownersOwnerDto[]yes
updated_atstring (date-time)yes
can_managebooleanyesWhether the caller may edit/delete schedules in this workspace.
bookmarkedbooleanyesWhether the CALLER has starred this one — per-user, unlike can_manage.
folder_idstring, nullablenoThe folder this row is grouped under, or None for "Uncategorized".
deleted_atstring (date-time), nullablenoSet only in the trash view; None for a live schedule.
StatusMeaning
200Schedules in this workspace

POST /api/ws/{workspace}/alerts​

Operation id: create. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.

Request body (application/json): CreateSchedule

FieldTypeRequiredDescription
typeScheduleTypeyesWhat a schedule does: evaluate a query (alert), deliver a rendering of a saved object (report), or watch a Data API endpoint's traffic (dataapi_alert, migration 0128).
namestringyes
descriptionstringno
activebooleanno
crontabstringyes
timezonestringno
database_idstring (uuid), nullableno
sqlstring, nullableno
validator_typeValidatorTypeno
validator_configobjectno
chart_idstring (uuid), nullableno
dashboard_idstring (uuid), nullableno
report_formatReportFormatno
custom_widthinteger (int32), nullableno
custom_heightinteger (int32), nullableno
dataapi_endpoint_idstring (uuid), nullablenoNone is workspace-scoped: watch every endpoint rather than one.
dataapi_metricDataapiMetricno
dataapi_error_codestring, nullablenoRequired, and only meaningful, when dataapi_metric is error_code_count — schedule_dataapi_error_code_needs_metric / schedule_dataapi_metric_needs_error_code (migration 0128).
dataapi_window_sinteger (int32), nullableno
grace_period_sinteger (int32), nullableno
working_timeout_sinteger (int32), nullableno
log_retention_daysinteger (int32), nullableno
email_subjectstring, nullableno
messagestring, nullablenoA user-authored note carried into the notification body. Distinct from description, which is the line the LIST shows.
message_footerstring, nullablenoThe closing note, rendered UNDER the result — message opens the notification, this one closes it, and an inline image sits between them. Defaulted, so a client written before 0116 keeps working unchanged.
skip_if_emptybooleannoMetabase's skip_if_empty: send nothing when the run produced no rows.
targetsTargetInput[]noObjects a REPORT delivers, in page order. Empty falls back to the single chart_id/dashboard_id, which is every pre-0115 row.
ownersstring (uuid)[]noOwner user ids. Empty means "the creator", resolved server-side — a schedule with no owner has no identity to run as (§5.2).
recipientsRecipientInput[]no

Response 200 (application/json): ScheduleDetailDto

FieldTypeRequiredDescription
idstringyes
typeScheduleTypeyesWhat a schedule does: evaluate a query (alert), deliver a rendering of a saved object (report), or watch a Data API endpoint's traffic (dataapi_alert, migration 0128).
namestringyes
descriptionstringyes
activebooleanyes
crontabstringyes
timezonestringyes
next_run_atstring (date-time), nullableno
database_idstring, nullableno
sqlstring, nullableno
validator_typeValidatorTypeno
validator_configobjectyes
last_stateRunStateno
last_eval_atstring (date-time), nullableno
last_valuenumber (double), nullableno
chart_idstring, nullableno
dashboard_idstring, nullableno
report_formatReportFormatno
custom_widthinteger (int32), nullableno
custom_heightinteger (int32), nullableno
dataapi_endpoint_idstring, nullableno
dataapi_metricDataapiMetricno
dataapi_error_codestring, nullableno
dataapi_window_sinteger (int32), nullableno
grace_period_sinteger (int32)yes
working_timeout_sinteger (int32)yes
log_retention_daysinteger (int32)yes
email_subjectstring, nullableno
messagestring, nullablenoA user-authored note carried into the notification body. Distinct from description, which is the line the LIST shows.
message_footerstring, nullablenoThe closing note, rendered UNDER the result — message opens the notification, this one closes it, and an inline image sits between them. Defaulted, so a client written before 0116 keeps working unchanged.
skip_if_emptybooleannoMetabase's skip_if_empty: send nothing when the run produced no rows.
targetsTargetInput[]noObjects a REPORT delivers, in page order. Empty falls back to the single chart_id/dashboard_id, which is every pre-0115 row.
ownersOwnerDto[]yes
recipientsRecipientDto[]yes
created_bystring, nullableno
updated_atstring (date-time)yes
StatusMeaning
200Created
400Invalid body
409Name already used by a schedule of this type

GET /api/ws/{workspace}/alerts/{id}​

Operation id: detail. Auth: Session cookie.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Response 200 (application/json): ScheduleDetailDto

FieldTypeRequiredDescription
idstringyes
typeScheduleTypeyesWhat a schedule does: evaluate a query (alert), deliver a rendering of a saved object (report), or watch a Data API endpoint's traffic (dataapi_alert, migration 0128).
namestringyes
descriptionstringyes
activebooleanyes
crontabstringyes
timezonestringyes
next_run_atstring (date-time), nullableno
database_idstring, nullableno
sqlstring, nullableno
validator_typeValidatorTypeno
validator_configobjectyes
last_stateRunStateno
last_eval_atstring (date-time), nullableno
last_valuenumber (double), nullableno
chart_idstring, nullableno
dashboard_idstring, nullableno
report_formatReportFormatno
custom_widthinteger (int32), nullableno
custom_heightinteger (int32), nullableno
dataapi_endpoint_idstring, nullableno
dataapi_metricDataapiMetricno
dataapi_error_codestring, nullableno
dataapi_window_sinteger (int32), nullableno
grace_period_sinteger (int32)yes
working_timeout_sinteger (int32)yes
log_retention_daysinteger (int32)yes
email_subjectstring, nullableno
messagestring, nullablenoA user-authored note carried into the notification body. Distinct from description, which is the line the LIST shows.
message_footerstring, nullablenoThe closing note, rendered UNDER the result — message opens the notification, this one closes it, and an inline image sits between them. Defaulted, so a client written before 0116 keeps working unchanged.
skip_if_emptybooleannoMetabase's skip_if_empty: send nothing when the run produced no rows.
targetsTargetInput[]noObjects a REPORT delivers, in page order. Empty falls back to the single chart_id/dashboard_id, which is every pre-0115 row.
ownersOwnerDto[]yes
recipientsRecipientDto[]yes
created_bystring, nullableno
updated_atstring (date-time)yes
StatusMeaning
200Schedule
404No such schedule in this workspace

PUT /api/ws/{workspace}/alerts/{id}​

Operation id: update. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Request body (application/json): UpdateSchedule

FieldTypeRequiredDescription
namestringyes
descriptionstringno
activebooleanyes
crontabstringyes
timezonestringno
database_idstring (uuid), nullableno
sqlstring, nullableno
validator_typeValidatorTypeno
validator_configobjectno
chart_idstring (uuid), nullableno
dashboard_idstring (uuid), nullableno
report_formatReportFormatno
custom_widthinteger (int32), nullableno
custom_heightinteger (int32), nullableno
dataapi_endpoint_idstring (uuid), nullablenoNone is workspace-scoped: watch every endpoint rather than one.
dataapi_metricDataapiMetricno
dataapi_error_codestring, nullablenoRequired, and only meaningful, when dataapi_metric is error_code_count — schedule_dataapi_error_code_needs_metric / schedule_dataapi_metric_needs_error_code (migration 0128).
dataapi_window_sinteger (int32), nullableno
grace_period_sinteger (int32), nullableno
working_timeout_sinteger (int32), nullableno
log_retention_daysinteger (int32), nullableno
email_subjectstring, nullableno
messagestring, nullablenoA user-authored note carried into the notification body. Distinct from description, which is the line the LIST shows.
message_footerstring, nullablenoThe closing note, rendered UNDER the result — message opens the notification, this one closes it, and an inline image sits between them. Defaulted, so a client written before 0116 keeps working unchanged.
skip_if_emptybooleannoMetabase's skip_if_empty: send nothing when the run produced no rows.
targetsTargetInput[]noObjects a REPORT delivers, in page order. Empty falls back to the single chart_id/dashboard_id, which is every pre-0115 row.
ownersstring (uuid)[]no
recipientsRecipientInput[]no

Response 200 (application/json): ScheduleDetailDto

FieldTypeRequiredDescription
idstringyes
typeScheduleTypeyesWhat a schedule does: evaluate a query (alert), deliver a rendering of a saved object (report), or watch a Data API endpoint's traffic (dataapi_alert, migration 0128).
namestringyes
descriptionstringyes
activebooleanyes
crontabstringyes
timezonestringyes
next_run_atstring (date-time), nullableno
database_idstring, nullableno
sqlstring, nullableno
validator_typeValidatorTypeno
validator_configobjectyes
last_stateRunStateno
last_eval_atstring (date-time), nullableno
last_valuenumber (double), nullableno
chart_idstring, nullableno
dashboard_idstring, nullableno
report_formatReportFormatno
custom_widthinteger (int32), nullableno
custom_heightinteger (int32), nullableno
dataapi_endpoint_idstring, nullableno
dataapi_metricDataapiMetricno
dataapi_error_codestring, nullableno
dataapi_window_sinteger (int32), nullableno
grace_period_sinteger (int32)yes
working_timeout_sinteger (int32)yes
log_retention_daysinteger (int32)yes
email_subjectstring, nullableno
messagestring, nullablenoA user-authored note carried into the notification body. Distinct from description, which is the line the LIST shows.
message_footerstring, nullablenoThe closing note, rendered UNDER the result — message opens the notification, this one closes it, and an inline image sits between them. Defaulted, so a client written before 0116 keeps working unchanged.
skip_if_emptybooleannoMetabase's skip_if_empty: send nothing when the run produced no rows.
targetsTargetInput[]noObjects a REPORT delivers, in page order. Empty falls back to the single chart_id/dashboard_id, which is every pre-0115 row.
ownersOwnerDto[]yes
recipientsRecipientDto[]yes
created_bystring, nullableno
updated_atstring (date-time)yes
StatusMeaning
200Updated
400Invalid body
404No such schedule in this workspace

DELETE /api/ws/{workspace}/alerts/{id}​

Operation id: remove. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes
StatusMeaning
200Deleted
404No such schedule in this workspace

PUT /api/ws/{workspace}/alerts/{id}/active​

Operation id: set_active. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Request body (application/json): SetActiveBody

FieldTypeRequiredDescription
activebooleanyes

Response 200 (application/json): ScheduleSummaryDto

FieldTypeRequiredDescription
idstringyes
typeScheduleTypeyesWhat a schedule does: evaluate a query (alert), deliver a rendering of a saved object (report), or watch a Data API endpoint's traffic (dataapi_alert, migration 0128).
namestringyes
descriptionstringyes
activebooleanyes
crontabstringyes
timezonestringyes
next_run_atstring (date-time), nullableno
last_stateRunStateno
last_eval_atstring (date-time), nullableno
ownersOwnerDto[]yes
updated_atstring (date-time)yes
can_managebooleanyesWhether the caller may edit/delete schedules in this workspace.
bookmarkedbooleanyesWhether the CALLER has starred this one — per-user, unlike can_manage.
folder_idstring, nullablenoThe folder this row is grouped under, or None for "Uncategorized".
deleted_atstring (date-time), nullablenoSet only in the trash view; None for a live schedule.
StatusMeaning
200Updated
404No such schedule in this workspace

POST /api/ws/{workspace}/alerts/{id}/bookmark​

Operation id: bookmark_add. Auth: Session cookie and X-Egret-CSRF header.

A bookmark is the CALLER's own, so it needs no alert:manage — a viewer may star what they can READ, which is now a permission that exists and is therefore checked rather than described.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Response 200 (application/json): Ack

FieldTypeRequiredDescription
okbooleanyes
StatusMeaning
200Bookmarked for the caller
401Not authenticated
500Internal error

DELETE /api/ws/{workspace}/alerts/{id}/bookmark​

Operation id: bookmark_remove. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Response 200 (application/json): Ack

FieldTypeRequiredDescription
okbooleanyes
StatusMeaning
200Bookmark removed for the caller
401Not authenticated
500Internal error

PATCH /api/ws/{workspace}/alerts/{id}/folder​

Operation id: set_folder. Auth: Session cookie and X-Egret-CSRF header. Forbidden (403): Needs alert:manage.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Request body (application/json): SetFolderBody

FieldTypeRequiredDescription
folder_idstring (uuid), nullablenonull moves the schedule back to Uncategorized.

Response 200 (application/json): Ack

FieldTypeRequiredDescription
okbooleanyes
StatusMeaning
200Moved
401Not authenticated
403Needs alert:manage
404No such schedule here
500Internal error

POST /api/ws/{workspace}/alerts/{id}/restore​

Operation id: restore. Auth: Session cookie and X-Egret-CSRF header. Forbidden (403): Needs alert:manage.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Response 200 (application/json): Ack

FieldTypeRequiredDescription
okbooleanyes
StatusMeaning
200Restored from the trash
401Not authenticated
403Needs alert:manage
404No such schedule here
500Internal error

POST /api/ws/{workspace}/alerts/{id}/run​

Operation id: run_now. Auth: Session cookie and X-Egret-CSRF header.

Run one schedule immediately (P5's "Run now"). Goes through the exact same AutomationRunner::run_now the tick's own claim loop calls evaluate_and_deliver through — see that function's doc comment for why a manual run is not a second evaluator and does not bypass the grace period. Returns the run-log row it just wrote, so the caller can show the result without a second request.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Response 200 (application/json): RunDto

FieldTypeRequiredDescription
idstringyes
stateRunStateyesSuperset's five run states, verbatim. They are the vocabulary that makes the list page legible — in particular noop ("ran, condition false") and grace ("would have fired, suppressed") are the two answers to "why didn't I get an email?",...
started_atstring (date-time)yes
ended_atstring (date-time), nullableno
valuenumber (double), nullableno
errorstring, nullableno
notification_sent_atstring (date-time), nullableno
StatusMeaning
200Ran once; the run-log row it wrote
404No such schedule in this workspace

GET /api/ws/{workspace}/alerts/{id}/runs​

Operation id: runs. Auth: Session cookie.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Response 200 (application/json): array of RunDto

FieldTypeRequiredDescription
idstringyes
stateRunStateyesSuperset's five run states, verbatim. They are the vocabulary that makes the list page legible — in particular noop ("ran, condition false") and grace ("would have fired, suppressed") are the two answers to "why didn't I get an email?",...
started_atstring (date-time)yes
ended_atstring (date-time), nullableno
valuenumber (double), nullableno
errorstring, nullableno
notification_sent_atstring (date-time), nullableno
StatusMeaning
200Recent runs, newest first

POST /api/ws/{workspace}/alerts/{id}/trash​

Operation id: trash. Auth: Session cookie and X-Egret-CSRF header. Forbidden (403): Needs alert:manage.

Move to the trash (soft delete), so the list keeps a Restore path and the scheduler stops claiming it — deleted_at IS NULL is part of the claim predicate, not merely a display filter.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
idpathstring (uuid)yesSchedule id
workspacepathstringyes

Response 200 (application/json): Ack

FieldTypeRequiredDescription
okbooleanyes
StatusMeaning
200Moved to the trash
401Not authenticated
403Needs alert:manage
404No such schedule here
500Internal error

GET /api/ws/{workspace}/notifications/slack​

Operation id: slack_get. Auth: Session cookie.

The print page's ONE request. Deliberately token-only: there is no WsContext extractor here, so an ordinary session cookie authenticates nothing on this route — widening it to sessions would make it a second, unaudited read path for any chart or dashboard. The workspace's Slack app.

Gated on SMTP_MANAGE — the same permission as the relay, and for the same reason: a bot token is workspace administration, not alert authoring. An editor who may write a schedule still may not swap the credential every schedule posts with.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.

Response 200 (application/json): SlackConfigDto

FieldTypeRequiredDescription
default_channelstring, nullableno
has_tokenbooleanyesAlways true when a row exists: token_secret_id is NOT NULL. It is reported anyway so the editor's "a token is stored" line reads the same field on both credential paths — see redact_recipient_config.
updated_atstring (date-time)yes
StatusMeaning
200The workspace's Slack app
404Not configured

PUT /api/ws/{workspace}/notifications/slack​

Operation id: slack_put. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.

Request body (application/json): SlackConfigBody

FieldTypeRequiredDescription
tokenstring, nullablenoThree-way, like SMTP's password: absent keeps the stored token, "" is rejected (a config with no token cannot deliver, so there is nothing sensible to store), a value replaces it. Required on first write.
default_channelstring, nullableno

Response 200 (application/json): SlackConfigDto

FieldTypeRequiredDescription
default_channelstring, nullableno
has_tokenbooleanyesAlways true when a row exists: token_secret_id is NOT NULL. It is reported anyway so the editor's "a token is stored" line reads the same field on both credential paths — see redact_recipient_config.
updated_atstring (date-time)yes
StatusMeaning
200Saved

DELETE /api/ws/{workspace}/notifications/slack​

Operation id: slack_delete. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.

Response 200 (application/json): Ack

FieldTypeRequiredDescription
okbooleanyes
StatusMeaning
200Removed

GET /api/ws/{workspace}/notifications/smtp​

Operation id: smtp_get. Auth: Session cookie.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.

Response 200 (application/json): SmtpConfigDto

FieldTypeRequiredDescription
hoststringyes
portinteger (int32)yes
usernamestring, nullableno
from_addressstringyes
from_namestring, nullableno
tls_modeTlsModeyesHow the connection is secured. Spelled out rather than inferred from the port: 587-means-STARTTLS is a convention, not a rule, and guessing wrong silently sends credentials in the clear.
has_passwordbooleanyesWhether a password is stored. The password itself is never returned.
updated_atstring (date-time)yes
StatusMeaning
200The workspace's SMTP settings, without the password
404Not configured

PUT /api/ws/{workspace}/notifications/smtp​

Operation id: smtp_put. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.

Request body (application/json): SmtpConfigBody

FieldTypeRequiredDescription
hoststringyes
portinteger (int32)yes
usernamestring, nullableno
from_addressstringyes
from_namestring, nullableno
tls_modeTlsModeyesHow the connection is secured. Spelled out rather than inferred from the port: 587-means-STARTTLS is a convention, not a rule, and guessing wrong silently sends credentials in the clear.
passwordstring, nullablenoOmitted means "keep the stored password"; "" means "remove it".

Response 200 (application/json): SmtpConfigDto

FieldTypeRequiredDescription
hoststringyes
portinteger (int32)yes
usernamestring, nullableno
from_addressstringyes
from_namestring, nullableno
tls_modeTlsModeyesHow the connection is secured. Spelled out rather than inferred from the port: 587-means-STARTTLS is a convention, not a rule, and guessing wrong silently sends credentials in the clear.
has_passwordbooleanyesWhether a password is stored. The password itself is never returned.
updated_atstring (date-time)yes
StatusMeaning
200Saved

DELETE /api/ws/{workspace}/notifications/smtp​

Operation id: smtp_delete. Auth: Session cookie and X-Egret-CSRF header.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.
StatusMeaning
200Removed

POST /api/ws/{workspace}/notifications/smtp/test​

Operation id: smtp_test. Auth: Session cookie and X-Egret-CSRF header.

Send a probe message.

This endpoint is the whole reason the settings page is trustworthy: "configured" and "configured correctly" are otherwise indistinguishable until an alert fires at 3am and silently does not arrive. The relay's own error text is returned verbatim, because "authentication failed" and "connection refused" send the operator to different places.

ParameterInTypeRequiredDescription
workspacepathstringyesWorkspace slug.

Request body (application/json): SmtpTestBody

FieldTypeRequiredDescription
tostring, nullablenoWhere to send the probe. Defaults to the configured from-address.
StatusMeaning
200The probe was accepted by the relay
400The relay refused; the message says why