Skip to content

icloud-photos-sync local server API 1.0

This document describes the API of icloud-photo-sync's web server. Parameters are passed as query strings.

Requests to an unknown endpoint, or with an unsupported method, are rejected with 400 and the message Method (<method>) not supported on endpoint <url>. Unexpected errors while handling a request are answered with 500 (see InternalError).


Servers

Description URL
The URL and port depend on your local setup - by default the webserver is exposed at port 80, below the configured web base path http://localhost:80

Endpoints


GET /api/state

Provides the current operational state of the application

Responses

{
    "state": "ready",
    "timestamp": 0,
    "nextSync": 0,
    "prevError": {
        "message": "string",
        "code": "string"
    },
    "prevTrigger": "sync",
    "progressMsg": "string",
    "progress": 10.12,
    "trustedPhoneNumbers": [
        {
            "id": 0,
            "maskedNumber": "+49 •••• •••••12"
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "required": [
        "state",
        "timestamp"
    ],
    "properties": {
        "state": {
            "type": "string",
            "enum": [
                "ready",
                "running",
                "blocked"
            ],
            "description": "`blocked` means the application is waiting for an MFA code"
        },
        "timestamp": {
            "type": "integer",
            "description": "Time of the last state change, in milliseconds since epoch"
        },
        "nextSync": {
            "type": "integer",
            "description": "Time of the next scheduled sync, in milliseconds since epoch (daemon mode only)"
        },
        "prevError": {
            "type": "object",
            "description": "The error of the last run, cleared when the next run starts",
            "properties": {
                "message": {
                    "type": "string"
                },
                "code": {
                    "type": "string"
                }
            }
        },
        "prevTrigger": {
            "type": "string",
            "enum": [
                "sync",
                "auth"
            ]
        },
        "progressMsg": {
            "type": "string"
        },
        "progress": {
            "type": "number",
            "description": "Progress of the current run in percent"
        },
        "trustedPhoneNumbers": {
            "type": "array",
            "description": "The trusted phone numbers of the account, available once an MFA code was required - the `id` is used as `phoneNumberId` for `/api/resend_mfa`",
            "items": {
                "type": "object",
                "required": [
                    "id",
                    "maskedNumber"
                ],
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "maskedNumber": {
                        "type": "string",
                        "example": "+49 •••• •••••12"
                    }
                }
            }
        }
    }
}

Refer to the common response description: InternalError.


GET /api/log

Provides all stored log entries since the last trigger

Input parameters

Parameter In Type Default Nullable Description
loglevel query string none No The minimum log level of the returned entries, defaults to 'none' (returning no entries)

Responses

[
    {
        "level": "debug",
        "time": 0,
        "source": "string",
        "message": "string"
    }
]
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "array",
    "items": {
        "type": "object",
        "required": [
            "level",
            "time",
            "source",
            "message"
        ],
        "properties": {
            "level": {
                "type": "string",
                "enum": [
                    "debug",
                    "info",
                    "warn",
                    "error"
                ]
            },
            "time": {
                "type": "integer",
                "description": "Time of the log entry, in milliseconds since epoch"
            },
            "source": {
                "type": "string"
            },
            "message": {
                "type": "string"
            }
        }
    }
}

Refer to the common response description: InternalError.


POST /api/reauthenticate

Requests the application to re-authenticate

Responses

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "Reauthentication requested"
        }
    }
}

Refer to the common response description: SyncInProgress.

Refer to the common response description: InternalError.


POST /api/sync

Requests the application to execute an ad-hoc sync

Description

The sync is only executed, if the application runs in daemon mode

Responses

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "Sync requested"
        }
    }
}

Refer to the common response description: SyncInProgress.

Refer to the common response description: InternalError.


POST /api/resend_mfa

Requests the tool to resend the MFA code utilizing the provided method

Input parameters

Parameter In Type Default Nullable Description
method query string No The selected resend method
phoneNumberId query integer 1 No The id of the trusted phone number (see `trustedPhoneNumbers` of `/api/state`), in case multiple trusted phone numbers are registered with the account. Ignored for the `device` method.

Responses

{
    "message": "Requesting MFA resend with method 'Device'"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "examples": [
                "Requesting MFA resend with method 'Device'",
                "Requesting MFA resend with method 'SMS' (Number ID: 1)",
                "Requesting MFA resend with method 'Voice' (Number ID: 2)"
            ]
        }
    }
}

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "Resend method does not match expected format"
        }
    }
}

Refer to the common response description: MFANotExpected.

Refer to the common response description: InternalError.


POST /api/mfa

Enters the MFA code for authentication

Input parameters

Parameter In Type Default Nullable Description
code query string No The MFA code provided by the trusted source

Responses

{
    "message": "Read MFA code: 123456"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "example": "Read MFA code: 123456"
        }
    }
}

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "Unexpected MFA code format! Expecting 6 digits"
        }
    }
}

Refer to the common response description: MFANotExpected.

Refer to the common response description: InternalError.


POST /api/subscribe

Creates a notification subscription

Request body

{
    "endpoint": "string",
    "expirationTime": 10.12,
    "keys": {
        "p256dh": "string",
        "auth": "string"
    }
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "type": "object",
    "required": [
        "endpoint",
        "keys"
    ],
    "properties": {
        "endpoint": {
            "type": "string",
            "minLength": 1
        },
        "expirationTime": {
            "type": "number"
        },
        "keys": {
            "type": "object",
            "required": [
                "p256dh",
                "auth"
            ],
            "properties": {
                "p256dh": {
                    "type": "string",
                    "minLength": 1
                },
                "auth": {
                    "type": "string",
                    "minLength": 1
                }
            }
        }
    }
}

Responses

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "Push subscription added successfully"
        }
    }
}

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "Unable to add push subscription"
        }
    }
}

Refer to the common response description: InternalError.


GET /api/vapid-public-key

Gets the VAPID public key, required for push notification support

Responses

{
    "publicKey": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "publicKey": {
            "type": "string"
        }
    }
}

Refer to the common response description: InternalError.


GET /metrics

Provides sync metrics in the Prometheus/OpenMetrics exposition format

Description

Only available if the Prometheus metrics export is enabled (--export-prometheus-metrics), otherwise the endpoint does not exist and the request is rejected with 400. The exposition format is negotiated through the Accept header, following the Prometheus content negotiation: OpenMetrics 1.0.0 and the Prometheus text formats 1.0.0 and 0.0.4 are supported, the Prometheus text format 0.0.4 is used as fallback. See the sync metrics documentation for the exposed metrics.

Input parameters

Parameter In Type Default Nullable Description
Accept header string No The accepted exposition formats, e.g. as sent by Prometheus

Responses

"string"
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "string"
}

"string"
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "string"
}

"string"
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "string"
}

Refer to the common response description: InternalError.


Common responses

This section describes common responses that are reused across operations.

SyncInProgress

The action cannot be performed, because a sync or authentication is currently in progress (the state is not ready)

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "Cannot perform action while sync is in progress"
        }
    }
}

MFANotExpected

No MFA code is expected at this time (the state is not blocked)

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "const": "MFA code not expected at this time."
        }
    }
}

InternalError

An unexpected error occurred while handling the request

{
    "message": "WEB_SERVER_UNKNOWN_ERR: ..."
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "properties": {
        "message": {
            "type": "string",
            "description": "The description of the error",
            "example": "WEB_SERVER_UNKNOWN_ERR: ..."
        }
    }
}