Appearance
imap-sync
8 endpoints.
GET /api/v1/imap-sync/destinations
Destinations
The three servers a migration may land on, plus what the source form needs to offer. Served rather than duplicated in the frontend so the page and the engine can never disagree about where "host1" is.
200 — Successful Response
json
{
"additionalProperties": true,
"type": "object",
"title": "Response Destinations Api V1 Imap Sync Destinations Get"
}POST /api/v1/imap-sync/test
Test Connection
Log in, list the folders, log out.
Offered because a mistyped password is the commonest reason a migration fails, and a form is a much better place to discover that than a job row. A refusal comes back as ok: false with the server's own words rather than as an HTTP error — the request itself was fine, and the page wants to render the reason beside the field that caused it.
Request body
json
{
"properties": {
"dest_slug": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Dest Slug"
},
"host": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Host"
},
"port": {
"anyOf": [
{
"type": "integer",
"maximum": 65535,
"minimum": 1
},
{
"type": "null"
}
],
"title": "Port"
},
"security": {
"type": "string",
"title": "Security",
"default": "ssl"
},
"user": {
"type": "string",
"title": "User"
},
"password": {
"type": "string",
"title": "Password"
}
},
"type": "object",
"required": [
"user",
"password"
],
"title": "TestRequest",
"description": "Log in and list, without creating anything.\n\n``dest_slug`` and ``host`` are the two ways to name a server, and exactly\none applies: a destination is picked from the presets, a source is typed in.\nGiving the slug wins, so the form cannot accidentally test a destination at\nan address that is not the preset's."
}200 — Successful Response
json
{
"additionalProperties": true,
"type": "object",
"title": "Response Test Connection Api V1 Imap Sync Test Post"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/imap-sync/jobs
List Jobs
This organisation's migrations, newest first.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
limit | query | no | integer |
200 — Successful Response
json
{
"type": "array",
"items": {
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"source_host": {
"type": "string",
"title": "Source Host"
},
"source_user": {
"type": "string",
"title": "Source User"
},
"dest_slug": {
"type": "string",
"title": "Dest Slug"
},
"dest_host": {
"type": "string",
"title": "Dest Host"
},
"dest_user": {
"type": "string",
"title": "Dest User"
},
"dry_run": {
"type": "boolean",
"title": "Dry Run"
},
"status": {
"type": "string",
"title": "Status"
},
"current_folder": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Current Folder"
},
"folders_total": {
"type": "integer",
"title": "Folders Total"
},
"folders_done": {
"type": "integer",
"title": "Folders Done"
},
"messages_total": {
"type": "integer",
"title": "Messages Total"
},
"messages_copied": {
"type": "integer",
"title": "Messages Copied"
},
"messages_skipped": {
"type": "integer",
"title": "Messages Skipped"
},
"messages_failed": {
"type": "integer",
"title": "Messages Failed"
},
"bytes_copied": {
"type": "integer",
"title": "Bytes Copied"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Error"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Created At"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Started At"
},
"finished_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Finished At"
},
"live": {
"type": "boolean",
"title": "Live"
}
},
"type": "object",
"required": [
"id",
"source_host",
"source_user",
"dest_slug",
"dest_host",
"dest_user",
"dry_run",
"status",
"current_folder",
"folders_total",
"folders_done",
"messages_total",
"messages_copied",
"messages_skipped",
"messages_failed",
"bytes_copied",
"error",
"created_at",
"started_at",
"finished_at",
"live"
],
"title": "JobSummary",
"description": "One row as the list renders it. No log and no credentials."
},
"title": "Response List Jobs Api V1 Imap Sync Jobs Get"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/imap-sync/jobs
Create Job
Create a migration and, unless told otherwise, start it.
Request body
json
{
"properties": {
"source_host": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"title": "Source Host"
},
"source_port": {
"type": "integer",
"maximum": 65535,
"minimum": 1,
"title": "Source Port",
"default": 993
},
"source_security": {
"type": "string",
"title": "Source Security",
"default": "ssl"
},
"source_user": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"title": "Source User"
},
"source_password": {
"type": "string",
"minLength": 1,
"title": "Source Password"
},
"dest_slug": {
"type": "string",
"title": "Dest Slug"
},
"dest_user": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"title": "Dest User"
},
"dest_password": {
"type": "string",
"minLength": 1,
"title": "Dest Password"
},
"dry_run": {
"type": "boolean",
"title": "Dry Run",
"default": false
},
"automap": {
"type": "boolean",
"title": "Automap",
"default": true
},
"exclude_folders": {
"anyOf": [
{
"type": "string",
"maxLength": 512
},
{
"type": "null"
}
],
"title": "Exclude Folders"
},
"max_message_mb": {
"anyOf": [
{
"type": "integer",
"maximum": 10000,
"minimum": 0
},
{
"type": "null"
}
],
"title": "Max Message Mb"
},
"start": {
"type": "boolean",
"title": "Start",
"default": true
}
},
"type": "object",
"required": [
"source_host",
"source_user",
"source_password",
"dest_slug",
"dest_user",
"dest_password"
],
"title": "JobCreate"
}201 — Successful Response
json
{
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"source_host": {
"type": "string",
"title": "Source Host"
},
"source_user": {
"type": "string",
"title": "Source User"
},
"dest_slug": {
"type": "string",
"title": "Dest Slug"
},
"dest_host": {
"type": "string",
"title": "Dest Host"
},
"dest_user": {
"type": "string",
"title": "Dest User"
},
"dry_run": {
"type": "boolean",
"title": "Dry Run"
},
"status": {
"type": "string",
"title": "Status"
},
"current_folder": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Current Folder"
},
"folders_total": {
"type": "integer",
"title": "Folders Total"
},
"folders_done": {
"type": "integer",
"title": "Folders Done"
},
"messages_total": {
"type": "integer",
"title": "Messages Total"
},
"messages_copied": {
"type": "integer",
"title": "Messages Copied"
},
"messages_skipped": {
"type": "integer",
"title": "Messages Skipped"
},
"messages_failed": {
"type": "integer",
"title": "Messages Failed"
},
"bytes_copied": {
"type": "integer",
"title": "Bytes Copied"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Error"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Created At"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Started At"
},
"finished_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Finished At"
},
"live": {
"type": "boolean",
"title": "Live"
},
"source_port": {
"type": "integer",
"title": "Source Port"
},
"source_security": {
"type": "string",
"title": "Source Security"
},
"dest_port": {
"type": "integer",
"title": "Dest Port"
},
"dest_security": {
"type": "string",
"title": "Dest Security"
},
"automap": {
"type": "boolean",
"title": "Automap"
},
"exclude_folders": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Exclude Folders"
},
"max_message_mb": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Max Message Mb"
},
"log": {
"type": "string",
"title": "Log"
}
},
"type": "object",
"required": [
"id",
"source_host",
"source_user",
"dest_slug",
"dest_host",
"dest_user",
"dry_run",
"status",
"current_folder",
"folders_total",
"folders_done",
"messages_total",
"messages_copied",
"messages_skipped",
"messages_failed",
"bytes_copied",
"error",
"created_at",
"started_at",
"finished_at",
"live",
"source_port",
"source_security",
"dest_port",
"dest_security",
"automap",
"exclude_folders",
"max_message_mb",
"log"
],
"title": "JobDetail"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}GET /api/v1/imap-sync/jobs/{job_id}
Get Job
One migration in full, transcript included. This is what the page polls while a run is going.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
job_id | path | yes | integer |
200 — Successful Response
json
{
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"source_host": {
"type": "string",
"title": "Source Host"
},
"source_user": {
"type": "string",
"title": "Source User"
},
"dest_slug": {
"type": "string",
"title": "Dest Slug"
},
"dest_host": {
"type": "string",
"title": "Dest Host"
},
"dest_user": {
"type": "string",
"title": "Dest User"
},
"dry_run": {
"type": "boolean",
"title": "Dry Run"
},
"status": {
"type": "string",
"title": "Status"
},
"current_folder": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Current Folder"
},
"folders_total": {
"type": "integer",
"title": "Folders Total"
},
"folders_done": {
"type": "integer",
"title": "Folders Done"
},
"messages_total": {
"type": "integer",
"title": "Messages Total"
},
"messages_copied": {
"type": "integer",
"title": "Messages Copied"
},
"messages_skipped": {
"type": "integer",
"title": "Messages Skipped"
},
"messages_failed": {
"type": "integer",
"title": "Messages Failed"
},
"bytes_copied": {
"type": "integer",
"title": "Bytes Copied"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Error"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Created At"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Started At"
},
"finished_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Finished At"
},
"live": {
"type": "boolean",
"title": "Live"
},
"source_port": {
"type": "integer",
"title": "Source Port"
},
"source_security": {
"type": "string",
"title": "Source Security"
},
"dest_port": {
"type": "integer",
"title": "Dest Port"
},
"dest_security": {
"type": "string",
"title": "Dest Security"
},
"automap": {
"type": "boolean",
"title": "Automap"
},
"exclude_folders": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Exclude Folders"
},
"max_message_mb": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Max Message Mb"
},
"log": {
"type": "string",
"title": "Log"
}
},
"type": "object",
"required": [
"id",
"source_host",
"source_user",
"dest_slug",
"dest_host",
"dest_user",
"dry_run",
"status",
"current_folder",
"folders_total",
"folders_done",
"messages_total",
"messages_copied",
"messages_skipped",
"messages_failed",
"bytes_copied",
"error",
"created_at",
"started_at",
"finished_at",
"live",
"source_port",
"source_security",
"dest_port",
"dest_security",
"automap",
"exclude_folders",
"max_message_mb",
"log"
],
"title": "JobDetail"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}DELETE /api/v1/imap-sync/jobs/{job_id}
Delete Job
Remove a finished migration from the list.
Soft, like every other read here filters for: a migration is a record of what was done to somebody's mailbox, and the row keeps its transcript for anyone who has to answer a question about it later.
Refused while it is running — retiring the row a worker is writing to would leave the worker logging into nothing, and the operator with no way to stop it. Cancel first.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
job_id | path | yes | integer |
204 — Successful Response
422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/imap-sync/jobs/{job_id}/run
Run Job
Start a migration, or run a finished one again.
Re-running is the supported way to finish an interrupted row and to pick up mail that arrived since the last pass: the engine compares message identities rather than tracking a position, so a second run copies only what the destination is missing. The counters are reset first so they describe THIS run — the transcript below them keeps the whole history.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
job_id | path | yes | integer |
200 — Successful Response
json
{
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"source_host": {
"type": "string",
"title": "Source Host"
},
"source_user": {
"type": "string",
"title": "Source User"
},
"dest_slug": {
"type": "string",
"title": "Dest Slug"
},
"dest_host": {
"type": "string",
"title": "Dest Host"
},
"dest_user": {
"type": "string",
"title": "Dest User"
},
"dry_run": {
"type": "boolean",
"title": "Dry Run"
},
"status": {
"type": "string",
"title": "Status"
},
"current_folder": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Current Folder"
},
"folders_total": {
"type": "integer",
"title": "Folders Total"
},
"folders_done": {
"type": "integer",
"title": "Folders Done"
},
"messages_total": {
"type": "integer",
"title": "Messages Total"
},
"messages_copied": {
"type": "integer",
"title": "Messages Copied"
},
"messages_skipped": {
"type": "integer",
"title": "Messages Skipped"
},
"messages_failed": {
"type": "integer",
"title": "Messages Failed"
},
"bytes_copied": {
"type": "integer",
"title": "Bytes Copied"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Error"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Created At"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Started At"
},
"finished_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Finished At"
},
"live": {
"type": "boolean",
"title": "Live"
},
"source_port": {
"type": "integer",
"title": "Source Port"
},
"source_security": {
"type": "string",
"title": "Source Security"
},
"dest_port": {
"type": "integer",
"title": "Dest Port"
},
"dest_security": {
"type": "string",
"title": "Dest Security"
},
"automap": {
"type": "boolean",
"title": "Automap"
},
"exclude_folders": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Exclude Folders"
},
"max_message_mb": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Max Message Mb"
},
"log": {
"type": "string",
"title": "Log"
}
},
"type": "object",
"required": [
"id",
"source_host",
"source_user",
"dest_slug",
"dest_host",
"dest_user",
"dry_run",
"status",
"current_folder",
"folders_total",
"folders_done",
"messages_total",
"messages_copied",
"messages_skipped",
"messages_failed",
"bytes_copied",
"error",
"created_at",
"started_at",
"finished_at",
"live",
"source_port",
"source_security",
"dest_port",
"dest_security",
"automap",
"exclude_folders",
"max_message_mb",
"log"
],
"title": "JobDetail"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}POST /api/v1/imap-sync/jobs/{job_id}/cancel
Cancel Job
Ask a running migration to stop after the message it is on.
Not a rollback: everything already copied stays copied. That is deliberate and it is also what makes cancelling safe — the run can be resumed later and will skip exactly what it already wrote.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
job_id | path | yes | integer |
200 — Successful Response
json
{
"properties": {
"id": {
"type": "integer",
"title": "Id"
},
"source_host": {
"type": "string",
"title": "Source Host"
},
"source_user": {
"type": "string",
"title": "Source User"
},
"dest_slug": {
"type": "string",
"title": "Dest Slug"
},
"dest_host": {
"type": "string",
"title": "Dest Host"
},
"dest_user": {
"type": "string",
"title": "Dest User"
},
"dry_run": {
"type": "boolean",
"title": "Dry Run"
},
"status": {
"type": "string",
"title": "Status"
},
"current_folder": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Current Folder"
},
"folders_total": {
"type": "integer",
"title": "Folders Total"
},
"folders_done": {
"type": "integer",
"title": "Folders Done"
},
"messages_total": {
"type": "integer",
"title": "Messages Total"
},
"messages_copied": {
"type": "integer",
"title": "Messages Copied"
},
"messages_skipped": {
"type": "integer",
"title": "Messages Skipped"
},
"messages_failed": {
"type": "integer",
"title": "Messages Failed"
},
"bytes_copied": {
"type": "integer",
"title": "Bytes Copied"
},
"error": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Error"
},
"created_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Created At"
},
"started_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Started At"
},
"finished_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Finished At"
},
"live": {
"type": "boolean",
"title": "Live"
},
"source_port": {
"type": "integer",
"title": "Source Port"
},
"source_security": {
"type": "string",
"title": "Source Security"
},
"dest_port": {
"type": "integer",
"title": "Dest Port"
},
"dest_security": {
"type": "string",
"title": "Dest Security"
},
"automap": {
"type": "boolean",
"title": "Automap"
},
"exclude_folders": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Exclude Folders"
},
"max_message_mb": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Max Message Mb"
},
"log": {
"type": "string",
"title": "Log"
}
},
"type": "object",
"required": [
"id",
"source_host",
"source_user",
"dest_slug",
"dest_host",
"dest_user",
"dry_run",
"status",
"current_folder",
"folders_total",
"folders_done",
"messages_total",
"messages_copied",
"messages_skipped",
"messages_failed",
"bytes_copied",
"error",
"created_at",
"started_at",
"finished_at",
"live",
"source_port",
"source_security",
"dest_port",
"dest_security",
"automap",
"exclude_folders",
"max_message_mb",
"log"
],
"title": "JobDetail"
}422 — Validation Error
json
{
"properties": {
"detail": {
"items": {
"properties": {
"loc": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
}
]
},
"type": "array",
"title": "Location"
},
"msg": {
"type": "string",
"title": "Message"
},
"type": {
"type": "string",
"title": "Error Type"
}
},
"type": "object",
"required": [
"loc",
"msg",
"type"
],
"title": "ValidationError"
},
"type": "array",
"title": "Detail"
}
},
"type": "object",
"title": "HTTPValidationError"
}