Skip to content

User#

pyticktick.models.v2.responses.user #

Pydantic models for user-related data returned by the TickTick API.

Unofficial API

These models are part of the unofficial TickTick API. They were created by reverse engineering the API. They may be incomplete or inaccurate.

Classes:

Name Description
ScoreByDayV2

The user's score for each day.

TaskByDayV2

The number of tasks both completed and not completed for a given day.

TaskByMonthV2

The number of tasks both completed and not completed for a given month.

TaskByWeekV2

The number of tasks both completed and not completed for a given week.

TaskCountV2

Model that represents the current task count for a given time period.

UserProfileV2

Model containing the user's profile information.

UserSignOnV2

Model for the response of a sign-on request via the V2 API.

UserSignOnWithTOTPV2

Model for the response of a sign-on request via the V2 API with TOTP.

UserStatisticsV2

Model for the response of a user statistics request via the V2 API.

UserStatusV2

Model for the response of a user status request via the V2 API.

ScoreByDayV2 #

Bases: RootModel[dict[date, int]]

The user's score for each day.

TaskByDayV2 #

Bases: RootModel[dict[date, TaskCountV2]]

The number of tasks both completed and not completed for a given day.

TaskByMonthV2 #

Bases: RootModel[dict[date, TaskCountV2]]

The number of tasks both completed and not completed for a given month.

TaskByWeekV2 #

Bases: RootModel[dict[date, TaskCountV2]]

The number of tasks both completed and not completed for a given week.

TaskCountV2 pydantic-model #

Bases: BaseModelV2

Model that represents the current task count for a given time period.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model that represents the current task count for a given time period.",
  "properties": {
    "completeCount": {
      "title": "Completecount",
      "type": "integer"
    },
    "notCompleteCount": {
      "title": "Notcompletecount",
      "type": "integer"
    }
  },
  "required": [
    "completeCount",
    "notCompleteCount"
  ],
  "title": "TaskCountV2",
  "type": "object"
}

Fields:

  • complete_count (int)
  • not_complete_count (int)

Validators:

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

UserProfileV2 pydantic-model #

Bases: BaseModelV2

Model containing the user's profile information.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model containing the user's profile information.",
  "properties": {
    "etimestamp": {
      "title": "Etimestamp"
    },
    "username": {
      "format": "email",
      "title": "Username",
      "type": "string"
    },
    "siteDomain": {
      "title": "Sitedomain",
      "type": "string"
    },
    "createdCampaign": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Createdcampaign"
    },
    "createdDeviceInfo": {
      "title": "Createddeviceinfo"
    },
    "filledPassword": {
      "title": "Filledpassword",
      "type": "boolean"
    },
    "accountDomain": {
      "title": "Accountdomain"
    },
    "extenalId": {
      "title": "Extenalid"
    },
    "email": {
      "title": "Email"
    },
    "verifiedEmail": {
      "title": "Verifiedemail",
      "type": "boolean"
    },
    "fakedEmail": {
      "title": "Fakedemail",
      "type": "boolean"
    },
    "phone": {
      "title": "Phone"
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "givenName": {
      "title": "Givenname"
    },
    "familyName": {
      "title": "Familyname"
    },
    "link": {
      "title": "Link"
    },
    "picture": {
      "title": "Picture",
      "type": "string"
    },
    "gender": {
      "title": "Gender"
    },
    "locale": {
      "title": "Locale",
      "type": "string"
    },
    "userCode": {
      "format": "uuid4",
      "title": "Usercode",
      "type": "string"
    },
    "verCode": {
      "title": "Vercode"
    },
    "verKey": {
      "title": "Verkey"
    },
    "externalId": {
      "title": "Externalid"
    },
    "phoneWithoutCountryCode": {
      "title": "Phonewithoutcountrycode"
    },
    "displayName": {
      "title": "Displayname",
      "type": "string"
    }
  },
  "required": [
    "etimestamp",
    "username",
    "siteDomain",
    "createdCampaign",
    "createdDeviceInfo",
    "filledPassword",
    "accountDomain",
    "extenalId",
    "email",
    "verifiedEmail",
    "fakedEmail",
    "phone",
    "givenName",
    "familyName",
    "link",
    "picture",
    "gender",
    "locale",
    "userCode",
    "verCode",
    "verKey",
    "externalId",
    "phoneWithoutCountryCode",
    "displayName"
  ],
  "title": "UserProfileV2",
  "type": "object"
}

Fields:

  • etimestamp (Any)
  • username (EmailStr)
  • site_domain (str)
  • created_campaign (str | None)
  • created_device_info (Any)
  • filled_password (bool)
  • account_domain (Any)
  • extenal_id (Any)
  • email (Any)
  • verified_email (bool)
  • faked_email (bool)
  • phone (Any)
  • name (str | None)
  • given_name (Any)
  • family_name (Any)
  • link (Any)
  • picture (str)
  • gender (Any)
  • locale (str)
  • user_code (UUID4)
  • ver_code (Any)
  • ver_key (Any)
  • external_id (Any)
  • phone_without_country_code (Any)
  • display_name (str)

Validators:

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

UserSignOnV2 pydantic-model #

Bases: BaseModelV2

Model for the response of a sign-on request via the V2 API.

The most important field is token, which is used for authentication during a session.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for the response of a sign-on request via the V2 API.\n\nThe most important field is `token`, which is used for authentication during a\nsession.",
  "properties": {
    "inboxId": {
      "description": "The user's inbox ID.",
      "title": "Inboxid",
      "type": "string"
    },
    "registerDate": {
      "description": "The date when the user registered for TickTick, in seconds since the epoch.",
      "format": "date-time",
      "title": "Registerdate",
      "type": "string"
    },
    "token": {
      "description": "The user's authentication token that is used for short-term authentication.",
      "title": "Token",
      "type": "string"
    },
    "userId": {
      "description": "The user's ID.",
      "title": "Userid",
      "type": "string"
    },
    "username": {
      "description": "The user's email address.",
      "format": "email",
      "title": "Username",
      "type": "string"
    },
    "activeTeamUser": {
      "title": "Activeteamuser",
      "type": "boolean"
    },
    "ds": {
      "title": "Ds",
      "type": "boolean"
    },
    "freeTrial": {
      "title": "Freetrial",
      "type": "boolean"
    },
    "freq": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Freq"
    },
    "gracePeriod": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Graceperiod"
    },
    "needSubscribe": {
      "title": "Needsubscribe",
      "type": "boolean"
    },
    "pro": {
      "title": "Pro",
      "type": "boolean"
    },
    "proEndDate": {
      "title": "Proenddate",
      "type": "string"
    },
    "proStartDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Prostartdate"
    },
    "subscribeFreq": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Subscribefreq"
    },
    "subscribeType": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Subscribetype"
    },
    "teamPro": {
      "title": "Teampro",
      "type": "boolean"
    },
    "teamUser": {
      "title": "Teamuser",
      "type": "boolean"
    },
    "userCode": {
      "format": "uuid4",
      "title": "Usercode",
      "type": "string"
    }
  },
  "required": [
    "inboxId",
    "registerDate",
    "token",
    "userId",
    "username",
    "activeTeamUser",
    "ds",
    "freeTrial",
    "needSubscribe",
    "pro",
    "proEndDate",
    "teamPro",
    "teamUser",
    "userCode"
  ],
  "title": "UserSignOnV2",
  "type": "object"
}

Fields:

  • inbox_id (str)
  • register_date (datetime)
  • token (str)
  • user_id (str)
  • username (EmailStr)
  • active_team_user (bool)
  • ds (bool)
  • free_trial (bool)
  • freq (str | None)
  • grace_period (bool | None)
  • need_subscribe (bool)
  • pro (bool)
  • pro_end_date (str)
  • pro_start_date (str | None)
  • subscribe_freq (str | None)
  • subscribe_type (str | None)
  • team_pro (bool)
  • team_user (bool)
  • user_code (UUID4)

Validators:

inbox_id pydantic-field #

inbox_id: str

The user's inbox ID.

register_date pydantic-field #

register_date: datetime

The date when the user registered for TickTick, in seconds since the epoch.

token pydantic-field #

token: str

The user's authentication token that is used for short-term authentication.

user_id pydantic-field #

user_id: str

The user's ID.

username pydantic-field #

username: EmailStr

The user's email address.

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

UserSignOnWithTOTPV2 pydantic-model #

Bases: BaseModelV2

Model for the response of a sign-on request via the V2 API with TOTP.

This model is used when the user has enabled two-factor authentication (2FA) via TOTP (Time-based One-Time Password).

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for the response of a sign-on request via the V2 API with TOTP.\n\nThis model is used when the user has enabled two-factor authentication (2FA) via\nTOTP (Time-based One-Time Password).",
  "properties": {
    "authId": {
      "description": "The authentication ID used for the sign-on request.",
      "title": "Authid",
      "type": "string"
    },
    "expireTime": {
      "description": "The expiration time of the authentication ID in seconds since the epoch.",
      "title": "Expiretime",
      "type": "integer"
    }
  },
  "required": [
    "authId",
    "expireTime"
  ],
  "title": "UserSignOnWithTOTPV2",
  "type": "object"
}

Fields:

Validators:

auth_id pydantic-field #

auth_id: str

The authentication ID used for the sign-on request.

expire_time pydantic-field #

expire_time: int

The expiration time of the authentication ID in seconds since the epoch.

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

UserStatisticsV2 pydantic-model #

Bases: BaseModelV2

Model for the response of a user statistics request via the V2 API.

Show JSON schema:
{
  "$defs": {
    "ScoreByDayV2": {
      "additionalProperties": {
        "type": "integer"
      },
      "description": "The user's score for each day.",
      "propertyNames": {
        "format": "date"
      },
      "title": "ScoreByDayV2",
      "type": "object"
    },
    "TaskByDayV2": {
      "additionalProperties": {
        "$ref": "#/$defs/TaskCountV2"
      },
      "description": "The number of tasks both completed and not completed for a given day.",
      "propertyNames": {
        "format": "date"
      },
      "title": "TaskByDayV2",
      "type": "object"
    },
    "TaskByMonthV2": {
      "additionalProperties": {
        "$ref": "#/$defs/TaskCountV2"
      },
      "description": "The number of tasks both completed and not completed for a given month.",
      "propertyNames": {
        "format": "date"
      },
      "title": "TaskByMonthV2",
      "type": "object"
    },
    "TaskByWeekV2": {
      "additionalProperties": {
        "$ref": "#/$defs/TaskCountV2"
      },
      "description": "The number of tasks both completed and not completed for a given week.",
      "propertyNames": {
        "format": "date"
      },
      "title": "TaskByWeekV2",
      "type": "object"
    },
    "TaskCountV2": {
      "additionalProperties": false,
      "description": "Model that represents the current task count for a given time period.",
      "properties": {
        "completeCount": {
          "title": "Completecount",
          "type": "integer"
        },
        "notCompleteCount": {
          "title": "Notcompletecount",
          "type": "integer"
        }
      },
      "required": [
        "completeCount",
        "notCompleteCount"
      ],
      "title": "TaskCountV2",
      "type": "object"
    }
  },
  "additionalProperties": false,
  "description": "Model for the response of a user statistics request via the V2 API.",
  "properties": {
    "score": {
      "title": "Score",
      "type": "integer"
    },
    "level": {
      "title": "Level",
      "type": "integer"
    },
    "yesterdayCompleted": {
      "title": "Yesterdaycompleted",
      "type": "integer"
    },
    "todayCompleted": {
      "title": "Todaycompleted",
      "type": "integer"
    },
    "totalCompleted": {
      "title": "Totalcompleted",
      "type": "integer"
    },
    "scoreByDay": {
      "$ref": "#/$defs/ScoreByDayV2"
    },
    "taskByDay": {
      "$ref": "#/$defs/TaskByDayV2"
    },
    "taskByWeek": {
      "$ref": "#/$defs/TaskByWeekV2"
    },
    "taskByMonth": {
      "$ref": "#/$defs/TaskByMonthV2"
    },
    "todayPomoCount": {
      "title": "Todaypomocount",
      "type": "integer"
    },
    "yesterdayPomoCount": {
      "title": "Yesterdaypomocount",
      "type": "integer"
    },
    "totalPomoCount": {
      "title": "Totalpomocount",
      "type": "integer"
    },
    "todayPomoDuration": {
      "title": "Todaypomoduration",
      "type": "integer"
    },
    "yesterdayPomoDuration": {
      "title": "Yesterdaypomoduration",
      "type": "integer"
    },
    "totalPomoDuration": {
      "title": "Totalpomoduration",
      "type": "integer"
    },
    "pomoGoal": {
      "title": "Pomogoal",
      "type": "integer"
    },
    "pomoDurationGoal": {
      "title": "Pomodurationgoal",
      "type": "integer"
    },
    "pomoByDay": {
      "additionalProperties": true,
      "title": "Pomobyday",
      "type": "object"
    },
    "pomoByWeek": {
      "additionalProperties": true,
      "title": "Pomobyweek",
      "type": "object"
    },
    "pomoByMonth": {
      "additionalProperties": true,
      "title": "Pomobymonth",
      "type": "object"
    }
  },
  "required": [
    "score",
    "level",
    "yesterdayCompleted",
    "todayCompleted",
    "totalCompleted",
    "scoreByDay",
    "taskByDay",
    "taskByWeek",
    "taskByMonth",
    "todayPomoCount",
    "yesterdayPomoCount",
    "totalPomoCount",
    "todayPomoDuration",
    "yesterdayPomoDuration",
    "totalPomoDuration",
    "pomoGoal",
    "pomoDurationGoal",
    "pomoByDay",
    "pomoByWeek",
    "pomoByMonth"
  ],
  "title": "UserStatisticsV2",
  "type": "object"
}

Fields:

  • score (int)
  • level (int)
  • yesterday_completed (int)
  • today_completed (int)
  • total_completed (int)
  • score_by_day (ScoreByDayV2)
  • task_by_day (TaskByDayV2)
  • task_by_week (TaskByWeekV2)
  • task_by_month (TaskByMonthV2)
  • today_pomo_count (int)
  • yesterday_pomo_count (int)
  • total_pomo_count (int)
  • today_pomo_duration (int)
  • yesterday_pomo_duration (int)
  • total_pomo_duration (int)
  • pomo_goal (int)
  • pomo_duration_goal (int)
  • pomo_by_day (dict[str, Any])
  • pomo_by_week (dict[str, Any])
  • pomo_by_month (dict[str, Any])

Validators:

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e

UserStatusV2 pydantic-model #

Bases: BaseModelV2

Model for the response of a user status request via the V2 API.

This user "status" is mainly about the user's subscription status, rather than their current activity on TickTick.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for the response of a user status request via the V2 API.\n\nThis user \"status\" is mainly about the user's subscription status, rather than\ntheir current activity on TickTick.",
  "properties": {
    "userId": {
      "description": "The user's ID.",
      "title": "Userid",
      "type": "string"
    },
    "userCode": {
      "format": "uuid4",
      "title": "Usercode",
      "type": "string"
    },
    "username": {
      "description": "The user's email address.",
      "format": "email",
      "title": "Username",
      "type": "string"
    },
    "teamPro": {
      "title": "Teampro",
      "type": "boolean"
    },
    "proStartDate": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The date when the user started their premium subscription.",
      "title": "Prostartdate"
    },
    "proEndDate": {
      "description": "The date when the user's premium subscription is slated to end.",
      "title": "Proenddate",
      "type": "string"
    },
    "registerDate": {
      "description": "The date when the user registered for TickTick, in seconds since the epoch.",
      "format": "date-time",
      "title": "Registerdate",
      "type": "string"
    },
    "subscribeType": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Subscribetype"
    },
    "subscribeFreq": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Subscribefreq"
    },
    "needSubscribe": {
      "title": "Needsubscribe",
      "type": "boolean"
    },
    "freq": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Freq"
    },
    "inboxId": {
      "description": "The user's inbox ID.",
      "title": "Inboxid",
      "type": "string"
    },
    "teamUser": {
      "title": "Teamuser",
      "type": "boolean"
    },
    "activeTeamUser": {
      "title": "Activeteamuser",
      "type": "boolean"
    },
    "freeTrial": {
      "title": "Freetrial",
      "type": "boolean"
    },
    "pro": {
      "description": "Whether or not a user has subscribed to the premium plan.",
      "title": "Pro",
      "type": "boolean"
    },
    "ds": {
      "title": "Ds",
      "type": "boolean"
    },
    "timeStamp": {
      "description": "Timestamp of the last update.",
      "title": "Timestamp",
      "type": "integer"
    },
    "gracePeriod": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Graceperiod"
    }
  },
  "required": [
    "userId",
    "userCode",
    "username",
    "teamPro",
    "proEndDate",
    "registerDate",
    "needSubscribe",
    "inboxId",
    "teamUser",
    "activeTeamUser",
    "freeTrial",
    "pro",
    "ds",
    "timeStamp"
  ],
  "title": "UserStatusV2",
  "type": "object"
}

Fields:

Validators:

inbox_id pydantic-field #

inbox_id: str

The user's inbox ID.

pro pydantic-field #

pro: bool

Whether or not a user has subscribed to the premium plan.

pro_end_date pydantic-field #

pro_end_date: str

The date when the user's premium subscription is slated to end.

pro_start_date pydantic-field #

pro_start_date: str | None = None

The date when the user started their premium subscription.

register_date pydantic-field #

register_date: datetime

The date when the user registered for TickTick, in seconds since the epoch.

time_stamp pydantic-field #

time_stamp: int

Timestamp of the last update.

user_id pydantic-field #

user_id: str

The user's ID.

username pydantic-field #

username: EmailStr

The user's email address.

empty_str_to_none pydantic-validator #

empty_str_to_none(v: Any) -> Any

Convert empty strings to None.

TickTick API responses sometimes conflates None and empty strings for optional fields. This validator ensures that empty strings are converted to None, which then allows for more consistent handling of the data within the library.

Parameters:

Name Type Description Default
v Any

The value to validate.

required

Returns:

Name Type Description
Any Any

The input value if it is not an empty string, otherwise None.

Source code in src/pyticktick/models/v2/models.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
@field_validator("*", mode="before")
@classmethod
def empty_str_to_none(cls, v: Any) -> Any:
    """Convert empty strings to None.

    TickTick API responses sometimes conflates `None` and empty strings for
    optional fields. This validator ensures that empty strings are converted to
    `None`, which then allows for more consistent handling of the data within the
    library.

    Args:
        v (Any): The value to validate.

    Returns:
        Any: The input value if it is not an empty string, otherwise `None`.
    """
    if isinstance(v, str) and len(v) == 0:
        return None
    return v

override_forbid_extra_message_injector pydantic-validator #

override_forbid_extra_message_injector(
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2

Provide a better error message for extra fields.

The TickTick V2 API is unofficial and may change without notice. As such, the models may not always be up to date with the API. This validator catches the extra_forbidden errors and provides a more informative error message, including a link to the documentation on how to override the extra_forbidden behavior if needed.

Parameters:

Name Type Description Default
data Any

The input data to validate.

required
handler ModelWrapValidatorHandler[BaseModelV2]

The handler to call the next validator in the chain.

required

Raises:

Type Description
ValidationError

If the pydantic model fails validation for any reason.

Returns:

Name Type Description
BaseModelV2 BaseModelV2

The validated model instance.

Source code in src/pyticktick/models/v2/models.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
@model_validator(mode="wrap")
@classmethod
def override_forbid_extra_message_injector(
    cls,
    data: Any,
    handler: ModelWrapValidatorHandler[BaseModelV2],
) -> BaseModelV2:
    """Provide a better error message for extra fields.

    The TickTick V2 API is unofficial and may change without notice. As such, the
    models may not always be up to date with the API. This validator catches the
    `extra_forbidden` errors and provides a more informative error message,
    including a link to the documentation on how to override the `extra_forbidden`
    behavior if needed.

    Args:
        data (Any): The input data to validate.
        handler (ModelWrapValidatorHandler[BaseModelV2]): The handler to call the
            next validator in the chain.

    Raises:
        ValidationError: If the pydantic model fails validation for any reason.

    Returns:
        BaseModelV2: The validated model instance.
    """  # noqa: DOC501, DOC502 # ruff thinks `from_exception_data` should be raised instead of `ValidationError`
    try:
        return handler(data)
    except ValidationError as e:
        errors = []
        for error_dict in e.errors():
            if error_dict.get("type") in (
                "extra_forbidden",
                "custom_pyticktick_extra_forbidden",
            ):
                _type: str | PydanticCustomError = PydanticCustomError(
                    "custom_pyticktick_extra_forbidden",
                    f"Extra inputs are not permitted by default for `{cls.__name__}`. Please set `override_forbid_extra` to `True` if you believe the TickTick API has diverged from the model. See https://pyticktick.pretzer.io/guides/settings/overriding_models_that_forbid_extra_fields/ for more information.",  # pyright: ignore[reportArgumentType] # ty: ignore[invalid-argument-type]
                )
            else:
                _type = error_dict["type"]

            init_error_details: InitErrorDetails = {
                "type": _type,
                "input": error_dict["input"],
            }
            if "loc" in error_dict:
                init_error_details["loc"] = error_dict["loc"]
            if "ctx" in error_dict:
                init_error_details["ctx"] = error_dict["ctx"]

            errors.append(init_error_details)

        raise ValidationError.from_exception_data(e.title, errors) from e