Skip to content

Settings#

pyticktick.settings #

Settings for the pyticktick client.

This module contains the settings for the pyticktick client. The settings juggle the two TickTick APIs: V1 and V2. The V1 API is the official API, and the V2 API is an undocumented one. The settings are expected to be used in conjunction with the pyticktick.client.Client class, which manages the API requests.

Classes:

Name Description
Settings

Settings for the pyticktick client.

TokenV1

Model for the V1 API token.

V2XDevice

Model for the V2 API X-Device header.

Settings #

Bases: BaseSettings

Settings for the pyticktick client.

The settings are used to sign on to the two TickTick APIs. The two APIs have two distinct sign on methods. The V1 API uses OAuth2, and is the official API, with official documentation. The V2 API uses a username and password, is an undocumented, and not officially supported by TickTick.

Each API can be signed on to independently, so a user can use one or both, depending on their needs. It is recommended to create and save the V1 token, as it requires user input to sign on, and is not easily automated.

Load all settings
from pyticktick import Settings

settings = Settings(
    v1_client_id="client_id",
    v1_client_secret="client_secret",
    v1_token={
        "value": "fa371b10-8b95-442b-b4a5-11a9959d3590",
        "expiration": 1701701789,
    },
    v2_username="username",
    v2_password="password",
    override_forbid_extra=True,
)
Load only V1 API settings
from pyticktick import Settings

settings = Settings(
    v1_client_id="client_id",
    v1_client_secret="client_secret",
    v1_token={
        "value": "fa371b10-8b95-442b-b4a5-11a9959d3590",
        "expiration": 1701701789,
    },
)
Load only V2 API settings
from pyticktick import Settings

settings = Settings(
    v2_username="username",
    v2_password="password",
)
Load only V2 API settings when 2FA is enabled
from pyticktick import Settings

settings = Settings(
    v2_username="username",
    v2_password="password",
    v2_totp_secret="totp_secret",
)

This class is a subclass of pydantic_settings.BaseSettings, which allows for environment variable and secret file parsing.

Load settings from environment variables
.bashrc
export PYTICKTICK_V1_CLIENT_ID="client_id"
export PYTICKTICK_V1_CLIENT_SECRET="client_secret"
export PYTICKTICK_V1_TOKEN_VALUE="fa371b10-8b95-442b-b4a5-11a9959d3590"
export PYTICKTICK_V1_TOKEN_EXPIRATION="1701701789"
export PYTICKTICK_V2_USERNAME="username"
export PYTICKTICK_V2_PASSWORD="password"
export PYTICKTICK_OVERRIDE_FORBID_EXTRA="True"
from pyticktick import Settings

settings = Settings()
Load settings from a secret file
.env
PYTICKTICK_V1_CLIENT_ID="client_id"
PYTICKTICK_V1_CLIENT_SECRET="client_secret"
PYTICKTICK_V1_TOKEN_VALUE="fa371b10-8b95-442b-b4a5-11a9959d3590"
PYTICKTICK_V1_TOKEN_EXPIRATION="1701701789"
PYTICKTICK_V2_USERNAME="username"
PYTICKTICK_V2_PASSWORD="password"
PYTICKTICK_OVERRIDE_FORBID_EXTRA="True"
from pyticktick import Settings

settings = Settings(_env_file=".env")

Attributes:

Name Type Description
v1_client_id Optional[str]

The client ID for the V1 API.

v1_client_secret Optional[SecretStr]

The client secret for the V1 API.

v1_token Optional[TokenV1]

The OAuth2 token for the V1 API.

v1_base_url HttpUrl

The base URL for the V1 API. Defaults to https://api.ticktick.com/open/v1/.

v1_oauth_redirect_url HttpUrl

The URL to redirect to after authorization. Defaults to http://127.0.0.1:8080/.

v2_username Optional[EmailStr]

The username for the V2 API.

v2_password Optional[SecretStr]

The password for the V2 API.

v2_totp_secret Optional[SecretStr]

The TOTP secret for the V2 API, required for two-factor authentication.

v2_token Optional[str]

The cookie token for the V2 API.

v2_base_url HttpUrl

The base URL for the V2 API. Defaults to https://api.ticktick.com/api/v2/.

v2_user_agent str

The User-Agent header for the V2 API, used to mimic a web browser request. Defaults to Mozilla/5.0 (rv:145.0) Firefox/145.0.

v2_x_device V2XDevice

The X-Device header for the V2 API, used to mimic a web browser request. Defaults to a JSON string with platform web, version 6430, and a random MongoDB ObjectId string as the ID.

override_forbid_extra bool

Whether to override forbidding extra fields.

Methods:

Name Description
v1_signon

Generate an OAuth2 token for the V1 API.

v2_signon

Generate a cookie token for the undocumented V2 API.

v1_headers property #

v1_headers: dict[str, str]

Get the headers dictionary for the V1 API.

Provides the headers dictionary for the V1 API. This is used to authenticate requests to the V1 API. The headers change as frequently as the V1 token, and therefore change, but rarely.

Returns:

Type Description
dict[str, str]

dict[str, str]: The headers dictionary for the V1 API.

Raises:

Type Description
ValueError

If the v1_token is not set.

v2_cookies property #

v2_cookies: dict[str, str]

Get the cookies dictionary for the V2 API.

Provides the cookies dictionary for the V2 API. This is used to authenticate requests to the V2 API. The cookies are only valid for the length of the client, and will change for each new client.

Returns:

Type Description
dict[str, str]

dict[str, str]: The cookies dictionary for the V2 API.

Raises:

Type Description
ValueError

If the v2_token is not set.

v2_headers property #

v2_headers: dict[str, str]

Get the headers dictionary for the V2 API.

Provides the headers dictionary for the V2 API. This is used to authenticate requests to the V2 API. The headers are static and do not change. They were taken from a web browser request to the TickTick website, and are meant to mimic a web browser request.

Returns:

Type Description
dict[str, str]

dict[str, str]: The headers dictionary for the V2 API.

v1_signon classmethod #

v1_signon(
    client_id: str,
    client_secret: str,
    oauth_redirect_url: str,
) -> OAuthTokenV1

Generate an OAuth2 token for the V1 API.

This method runs the OAuth2 sign on process for the V1 API. This is a multi-step process that requires user input, so its use is limited to interactive sessions.

V1 OAuth2 Sign On Process

The multi-step process is as follows:

  1. The user is redirected to the authorization URL, where they log in, and authorize the application.
  2. The user is redirected to a new URL, which contains a code parameter. This URL should be copied into the console, and the code extracted.
  3. The code is exchanged for an OAuth2 token. This token is then used for authentication moving forward.

You can read the official documentation here.

Parameters:

Name Type Description Default
client_id str

The client ID for the application.

required
client_secret str

The client secret for the application.

required
oauth_redirect_url str

The URL to redirect to after authorization.

required

Returns:

Name Type Description
OAuthTokenV1 OAuthTokenV1

The OAuth2 token response model for the V1 API.

Source code in src/pyticktick/settings.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
@classmethod
def v1_signon(
    cls,
    client_id: str,
    client_secret: str,
    oauth_redirect_url: str,
) -> OAuthTokenV1:
    """Generate an OAuth2 token for the V1 API.

    This method runs the OAuth2 sign on process for the V1 API. This is a multi-step
    process that requires user input, so its use is limited to interactive sessions.

    ???+ note "V1 OAuth2 Sign On Process"
        The multi-step process is as follows:

        1. The user is redirected to the authorization URL, where they log in, and
        authorize the application.
        2. The user is redirected to a new URL, which contains a `code` parameter.
        This URL should be copied into the console, and the code extracted.
        3. The code is exchanged for an OAuth2 token. This token is then used for
        authentication moving forward.

        You can read the official documentation [here](https://developer.ticktick.com/docs/index.html#/openapi?id=authorization).

    Args:
        client_id (str): The client ID for the application.
        client_secret (str): The client secret for the application.
        oauth_redirect_url (str): The URL to redirect to after authorization.

    Returns:
        OAuthTokenV1: The OAuth2 token response model for the V1 API.
    """
    resp = cls._v1_signon(client_id, client_secret, oauth_redirect_url)
    return OAuthTokenV1.model_validate(resp)

v2_signon classmethod #

v2_signon(
    username: str,
    password: str,
    totp_secret: str | None,
    base_url: str,
    headers: dict[str, str],
) -> UserSignOnV2

Generate a cookie token for the undocumented V2 API.

This method uses a username and password to sign on to the V2 API. The sign on request returns a cookie token, which is then used for authentication moving forward. This API is undocumented and TickTick may change it at any time. This logic was mainly pulled lucasvtiradentes/ticktick-api-lvt:

  1. The headers and url base were taken from here.
  2. The url route was taken from here.

Parameters:

Name Type Description Default
username str

The username for the V2 API.

required
password str

The password for the V2 API.

required
totp_secret str | None

The TOTP secret for the V2 API, used for two-factor authentication. If the sign on request requires TOTP verification, this parameter must be provided. If the sign on request does not require TOTP verification, this parameter can be None.

required
base_url str

The base URL for the V2 API.

required
headers dict[str, str]

The headers dictionary for the V2 API.

required

Raises:

Type Description
ValueError

If the sign on request requires TOTP verification, but no TOTP was provided.

Returns:

Name Type Description
UserSignOnV2 UserSignOnV2

The sign on response model for the V2 API.

Source code in src/pyticktick/settings.py
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
@classmethod
def v2_signon(
    cls,
    username: str,
    password: str,
    totp_secret: str | None,
    base_url: str,
    headers: dict[str, str],
) -> UserSignOnV2:
    """Generate a cookie token for the undocumented V2 API.

    This method uses a username and password to sign on to the V2 API. The sign on
    request returns a cookie token, which is then used for authentication moving
    forward. This API is undocumented and TickTick may change it at any time. This
    logic was mainly pulled [lucasvtiradentes/ticktick-api-lvt](https://github.com/lucasvtiradentes/ticktick-api-lvt):

    1. The headers and url base were taken from [here](https://github.com/lucasvtiradentes/ticktick-api-lvt/blob/2b121beacf8d93e4408e194dc7ea9b8ac9553988/src/configs.ts#L25-L26).
    2. The url route was taken from [here](https://github.com/lucasvtiradentes/ticktick-api-lvt/blob/2b121beacf8d93e4408e194dc7ea9b8ac9553988/src/routes/auth/login.ts#L6).

    Args:
        username (str): The username for the V2 API.
        password (str): The password for the V2 API.
        totp_secret (str | None): The TOTP secret for the V2 API, used for
            two-factor authentication. If the sign on request requires TOTP
            verification, this parameter must be provided. If the sign on request
            does not require TOTP verification, this parameter can be `None`.
        base_url (str): The base URL for the V2 API.
        headers (dict[str, str]): The headers dictionary for the V2 API.

    Raises:
        ValueError: If the sign on request requires TOTP verification, but no TOTP
            was provided.

    Returns:
        UserSignOnV2: The sign on response model for the V2 API.
    """
    resp = cls._v2_signon(
        username=username,
        password=password,
        base_url=base_url,
        headers=headers,
    )
    try:
        totp_resp = UserSignOnWithTOTPV2.model_validate(resp)
        if totp_secret is None:
            msg = "Sign on requires TOTP verification, but no TOTP was provided."
            logger.error(msg)
            raise ValueError(msg)
        resp = cls._v2_mfa_verify(
            totp_secret=totp_secret,
            auth_id=totp_resp.auth_id,
            base_url=base_url,
            headers=headers,
        )
    except ValidationError:
        pass

    return UserSignOnV2.model_validate(resp)

TokenV1 pydantic-model #

Bases: BaseModel

Model for the V1 API token.

The token is a standard UUID4 string, which seems to expire after about 6 months. The expiration is a Unix timestamp in seconds, which is validated to confirm that the token has not expired.

Show JSON schema:
{
  "additionalProperties": false,
  "description": "Model for the V1 API token.\n\nThe token is a standard UUID4 string, which seems to [expire after about 6 months](https://github.com/lazeroffmichael/ticktick-py/blob/9ebc0c5b09c702de8a137a05dc5b8d8803f18f48/docs/index.md?plain=1#L148).\nThe expiration is a Unix timestamp in seconds, which is validated to confirm that\nthe token has not expired.",
  "properties": {
    "value": {
      "description": "The UUID4 string token",
      "format": "uuid4",
      "title": "Value",
      "type": "string"
    },
    "expiration": {
      "description": "The Unix timestamp in seconds when the token expires.",
      "title": "Expiration",
      "type": "integer"
    }
  },
  "required": [
    "value",
    "expiration"
  ],
  "title": "TokenV1",
  "type": "object"
}

Config:

  • extra: forbid

Fields:

Validators:

expiration pydantic-field #

expiration: int

The Unix timestamp in seconds when the token expires.

value pydantic-field #

value: UUID4

The UUID4 string token

V2XDevice pydantic-model #

Bases: BaseModel

Model for the V2 API X-Device header.

The X-Device header is used to mimic a web browser request. It requires a platform, version, and id. The id is a randomly generated MongoDB ObjectId() string.

You are able to pass in extra fields, as the X-Device header may change over time, but these three fields are the only known required ones, as found via trial and error.

Show JSON schema:
{
  "additionalProperties": true,
  "description": "Model for the V2 API X-Device header.\n\nThe X-Device header is used to mimic a web browser request. It requires a\n`platform`, `version`, and `id`. The `id` is a randomly generated MongoDB\nObjectId() string.\n\nYou are able to pass in extra fields, as the X-Device header may change over time,\nbut these three fields are the only known required ones, as found via trial and\nerror.",
  "properties": {
    "platform": {
      "default": "web",
      "description": "The platform of the device.",
      "title": "Platform",
      "type": "string"
    },
    "version": {
      "default": 6430,
      "description": "The version of the device.",
      "title": "Version",
      "type": "integer"
    },
    "id": {
      "description": "Randomly generated id, should be a MongoDB ObjectId().",
      "title": "Id",
      "type": "string"
    }
  },
  "title": "V2XDevice",
  "type": "object"
}

Config:

  • extra: allow

Fields:

id pydantic-field #

id: str

Randomly generated id, should be a MongoDB ObjectId().

platform pydantic-field #

platform: str = 'web'

The platform of the device.

version pydantic-field #

version: int = 6430

The version of the device.