Skip to content

Planka Interface

interface

Base interface for Planka

When reading the documentation, all returned list[PlankaModel] types are actually models.ModelLists at runtime. These will also be properly type hinted by your static type checker and expose some alternate ways of indexing into model lists:

Example:

>>> type(planka.projects)
ModelList

# Using an exact schema filter
>>> planka.projects[{'name': 'My Project'}]
[Project(name='My Project', ...)]

# Using a functional schema filter (name is replaced with the value of name)
>>> planka.projects[{'name': lambda name: 'My' in name}]
[Project(name='My Project', ...), Project(name='My Other Project', ...)]

# Using a model filter
>>> planka.projects[lambda project: project.owner == planka.me]
[<previous results>..., Project('Another Project I Own', ...)]

All dictionary based schema filtering can be done per key and the model will only be included in the output if all filters match.

Additionally, a dpop method is included that allows popping from a model list with a default value if no results

>>> filtered = to_do_list.cards[lambda c: c.due_date and (c.due_date - datetime.now()).days < 4]
>>> if next_card := filtered.dpop():
...     print(next_card.url)
...     print(next_card.name)
... else:
...     print('No results')
https://planka.mydomain.com/cards/1234...
'Critical Project'
--or--
No results

CLASS DESCRIPTION
Planka

Root object for connecting to a Planka instance

Planka

Planka(base_url: str | URL | None = None, *, client: Client | None = None, timezone: timezone = utc)

Root object for connecting to a Planka instance

A Planka instance can be initialized using a base_url or a httpx.Client objcet. If both arguments are passed, the base_url of the passed client will be overriden with the url passed to the base_url argument

Example
# Using the default client
>>> planka = Planka('https://planka.example.com')
... planka.client
<httpx.Client object at 0x...>

>>> planka.client.base_url
URL('https://planka.example.com')

# Using a pre-configured client
>>> hooks = {'request': [hook1, hook2], 'response': [hook3, hook4]}
... client = Client(event_hooks=hooks)
... planka = Planka('https://planka.example.com', client=client)
... planka.client.event_hooks
{'request': [<hook1>, <hook2>], 'response': [<hook3>, <hook4>]}

All Planka sessions will respect the configuration of the passed client object. For more configuration options, see the httpx docs: https://www.python-httpx.org/advanced/clients/

After initializing, the Planka instance required the authorization flow to take place using the login method

Example

>>> # Using an API key
... planka.login(api_key='<my_api_key>')
... planka.projects
[Project(...), Project(...), ...]
>>> # First time login (accept instance ToS)
... planka.login(username='me@email.com', password='mypassword', accept_terms=True)
TERMS OF SERVICE
--- More ToS ---

>>> planka.projects
[Project(...), Project(...), ...]

Logging in with a username and password will work, but it's best practice to authenticate using an api key, which you can get from your instance administrator.

PARAMETER DESCRIPTION

base_url

The base url of the instance (e.g. https://planka.app)

TYPE: str | URL | None DEFAULT: None

client

An optional pre-configured httpx.Client object to use as the session client

TYPE: Client | None DEFAULT: None

timezone

An optional timezone to cast all datetimes to for date math

TYPE: timezone DEFAULT: utc

RAISES DESCRIPTION
ValueError

If no base_url or no client with a base_url

METHOD DESCRIPTION
accept_terms

If the User has never logged on, or is required to accept new terms, allow them to do so

create_project

Creates a project. The current user automatically becomes a project manager.

create_user

Creates a user account. Requires admin privileges.

create_webhook

Create a Webhook. Requires admin

login

Authenticate with the planka instance

logout

Logout the current User

read_notifications

Read all Notifications for the current User

update_smtp_config

Update the server SMTP config (all args are optional and only passed args will be updated)

ATTRIBUTE DESCRIPTION
bootstrap

Get the application bootstrap

config

(deprecated: Use Planka.bootstrap instead) Get the configuration info for the current Planka server

TYPE: Config

me

Get the User object for the currently logged in user

TYPE: User

notifications

Get all notifications for the current User

TYPE: list[Notification]

projects

Get all Projects available to the current user

TYPE: list[Project]

smtp_config

Get the server SMTP config (this also tests the current config)

unread_notifications

Get all unread Notifications for the current user

TYPE: list[Notification]

users

Get all Users on the current instance (requires admin or projectOwner role)

TYPE: list[User]

webhooks

Get all configured Webhooks (requires admin)

TYPE: list[Webhook]

Source code in src/plankapy/v2/interface.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def __init__(self, 
             base_url: str|URL|None=None, 
             *, 
             client: Client|None=None, 
             timezone: timezone = timezone.utc) -> None:
    """
    Args:
        base_url: The base url of the instance (e.g. `https://planka.app`)
        client: An optional pre-configured `httpx.Client` object to use as the session client
        timezone: An optional timezone to cast all datetimes to for date math

    Raises:
        ValueError: If no base_url or no client with a base_url
    """
    if client is None and base_url:
        self.client = Client(base_url=base_url)
    elif client and base_url is None:
        if not client.base_url:
            raise ValueError(
                f'If using a client, the client\'s base_url attribute must be set '
                'or a base_url must be passed to the Planka initializer'
            )
        self.client = client
    elif base_url and client:
        self.client = client
        self.client.base_url = base_url
    else:
        raise ValueError(f'base_url and/or client must be passed')

    self.endpoints = PlankaEndpoints(self.client)
    self.timezone = timezone

    # Assigned after login() is called
    self.current_role: UserRole | None = None
    self.current_id : str | None = None

bootstrap property

bootstrap

Get the application bootstrap

config cached property

config: Config

(deprecated: Use Planka.bootstrap instead) Get the configuration info for the current Planka server

me cached property

me: User

Get the User object for the currently logged in user

notifications property

notifications: list[Notification]

Get all notifications for the current User

projects property

projects: list[Project]

Get all Projects available to the current user

Note

admins will get all instance Projects projectOwners will get all owned projects and shared projects all others will get only assigned and shared projects

smtp_config property

smtp_config

Get the server SMTP config (this also tests the current config)

unread_notifications property

unread_notifications: list[Notification]

Get all unread Notifications for the current user

users property

users: list[User]

Get all Users on the current instance (requires admin or projectOwner role)

Note

projectOwners will only get Users in their Projects admins will get all instance Users all others will get an empty list

webhooks property

webhooks: list[Webhook]

Get all configured Webhooks (requires admin)

accept_terms

accept_terms(pending_token: str, lang: Language | None = None)

If the User has never logged on, or is required to accept new terms, allow them to do so

Source code in src/plankapy/v2/interface.py
156
157
158
159
160
161
162
163
164
def accept_terms(self, pending_token: str, lang: Language | None = None):
    """If the User has never logged on, or is required to accept new terms, allow them to do so"""
    if lang:
        terms = self.endpoints.getTerms(language=lang)['item']
    else:
        terms = self.endpoints.getTerms()['item']
    print(terms['content'])
    sig = terms['signature']
    self.endpoints.acceptTerms(pendingToken=pending_token, signature=sig)

create_project

create_project(*, name: str, type: ProjectType, description: str | None = None) -> Project

Creates a project. The current user automatically becomes a project manager.

Must be a Project Owner or an Admin

PARAMETER DESCRIPTION
type

Type of the project

TYPE: ProjectType

name

Name/title of the project

TYPE: str

description

Detailed description of the project

TYPE: str | None DEFAULT: None

Source code in src/plankapy/v2/interface.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
def create_project(self, 
                   *,
                   name: str,
                   type: ProjectType,
                   description: str|None=None) -> Project:
    """Creates a project. The current user automatically becomes a project manager.

    Must be a Project Owner or an Admin

    Args:
        type: Type of the project
        name: Name/title of the project
        description: Detailed description of the project
    """
    return Project(
        self.endpoints.createProject(
            name=name, 
            type=type, 
            description=description,
        )['item'], 
        self
    )

create_user

create_user(*, email: str, password: str, role: UserRole, name: str, username: str | None = None, phone: str | None = None, organization: str | None = None, language: Language | None = None, subscribe_to_own_cards: bool = False, subscribe_to_cards_when_commenting: bool = True, turn_off_recent_card_highlighting: bool = False) -> User

Creates a user account. Requires admin privileges.

Only email, password, role, and name are required

PARAMETER DESCRIPTION
email

Email address for login and notifications

TYPE: str

password

Password for user authentication (must meet password requirements)

TYPE: str

role

User role defining access permissions

TYPE: UserRole

name

Full display name of the user

TYPE: str

username

Unique username for user identification

TYPE: str DEFAULT: None

phone

Contact phone number

TYPE: str DEFAULT: None

organization

Organization or company name

TYPE: str DEFAULT: None

language

Preferred language for user interface and notifications (example: en-US)

TYPE: LanguageCode DEFAULT: None

subscribe_to_own_cards

Whether the user subscribes to their own cards

TYPE: bool DEFAULT: False

subscribe_to_cards_when_commenting

Whether the user subscribes to cards when commenting

TYPE: bool DEFAULT: True

turn_off_recent_card_highlighting

Whether recent card highlighting is disabled

TYPE: bool DEFAULT: False

Source code in src/plankapy/v2/interface.py
326
327
328
329
330
331
332
333
334
335
336
337
338
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
def create_user(self, 
                *,
                email: str,
                password: str,
                role: UserRole,
                name: str,
                username: str|None=None,
                phone: str|None=None,
                organization: str|None=None,
                language: Language|None=None,
                subscribe_to_own_cards: bool=False,
                subscribe_to_cards_when_commenting: bool=True,
                turn_off_recent_card_highlighting: bool=False) -> User:
    """Creates a user account. Requires admin privileges.

    Only `email`, `password`, `role`, and `name` are required

    Args:
        email (str): Email address for login and notifications
        password (str): Password for user authentication (must meet password requirements)
        role (UserRole): User role defining access permissions
        name (str): Full display name of the user
        username (str): Unique username for user identification
        phone (str): Contact phone number
        organization (str): Organization or company name
        language (LanguageCode): Preferred language for user interface and notifications (example: `en-US`)
        subscribe_to_own_cards (bool): Whether the user subscribes to their own cards
        subscribe_to_cards_when_commenting (bool): Whether the user subscribes to cards when commenting
        turn_off_recent_card_highlighting (bool): Whether recent card highlighting is disabled
    """

    return User(
        self.endpoints.createUser(
            email=email,
            password=password,
            role=role,
            name=name,
            username=username,
            phone=phone,
            organization=organization,
            language=language,
            subscribeToOwnCards=subscribe_to_own_cards,
            subscribeToCardWhenCommenting=subscribe_to_cards_when_commenting,
            turnOffRecentCardHighlighting=turn_off_recent_card_highlighting,
        )['item'], 
        self
    )

create_webhook

create_webhook(*, name: str, url: str, access_token: str | None = None, events: Sequence[PlankaEvent] | None = None, excluded_events: Sequence[PlankaEvent] | None = None) -> Webhook

Create a Webhook. Requires admin

PARAMETER DESCRIPTION
name

Name/title of the webhook

TYPE: str

url

URL endpoint for the webhook

TYPE: str

access_token

Access token for webhook authentication

TYPE: str | None DEFAULT: None

events

list of events that trigger the webhook

TYPE: Sequence[PlankaEvent] | None DEFAULT: None

excluded_events

Comma-separated list of events excluded from the webhook

TYPE: Sequence[PlankaEvent] | None DEFAULT: None

Source code in src/plankapy/v2/interface.py
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
def create_webhook(self, 
                   *,
                   name: str,
                   url: str,
                   access_token: str|None=None,
                   events: Sequence[events.PlankaEvent]|None=None,
                   excluded_events: Sequence[events.PlankaEvent]|None=None) -> Webhook:
    """Create a Webhook. Requires admin

    Args:
        name: Name/title of the webhook
        url: URL endpoint for the webhook
        access_token: Access token for webhook authentication
        events: list of events that trigger the webhook
        excluded_events: Comma-separated list of events excluded from the webhook
    """
    args = {
        'name': name,
        'url': url
    }
    if events:
        args['events'] = ','.join(events)
    if excluded_events:
        args['excludedEvents'] = ','.join(excluded_events)
    if access_token:
        args['accessToken'] = access_token
    return Webhook(self.endpoints.createWebhook(**args)['item'], self)

login

login(*, username: str | None = None, password: str | None = None, api_key: str | None = None, accept_terms: bool | None = None, terms_lang: Language | None = None) -> None

Authenticate with the planka instance

PARAMETER DESCRIPTION
username

User username/email

TYPE: str | None DEFAULT: None

password

User password

TYPE: str | None DEFAULT: None

api_key

User API Key

TYPE: str | None DEFAULT: None

accept_terms

Set to True to accept terms on first login

TYPE: bool | None DEFAULT: None

terms_lang

If accepting terms, request them in this language

TYPE: Language | None DEFAULT: None

Note

After logging in for the first time, please get an API key from the Planka server.

Source code in src/plankapy/v2/interface.py
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
def login(self, 
          *, 
          username: str | None = None, 
          password: str | None = None, 
          api_key: str | None = None, 
          accept_terms: bool | None = None,
          terms_lang: Language | None = None) -> None:

    """Authenticate with the planka instance

    Args:
        username: User username/email 
        password: User password
        api_key: User API Key
        accept_terms: Set to `True` to accept terms on first login
        terms_lang: If accepting terms, request them in this language

    Note:
        After logging in for the first time, please get an API key from the Planka server.
    """
    # API Key
    if api_key:
        self.client.headers['X-Api-Key'] = api_key

    # User/Pass with term acceptance flow
    elif username and password:
        try:
            # Get Bearer Auth
            token = self.endpoints.createAccessToken(emailOrUsername=username, password=password, withHttpOnlyToken=True)['item']
            self.client.headers['Authorization'] = f'Bearer {token}'
        except HTTPStatusError as e:
            if not accept_terms:
                raise PermissionError(f'Please logon again with `accept_terms` set to `True` to login the first time')
            self.accept_terms(e.response.json()['pendingToken'], lang=terms_lang)
            self.login(username=username, password=password)

    # Invalid Creds
    else:
        raise PermissionError(f'No credentials supplied! Must provide a user/password or an api_key')

    self.current_role = self.me.role
    self.current_id = self.me.id

logout

logout() -> None

Logout the current User

Source code in src/plankapy/v2/interface.py
209
210
211
def logout(self) -> None:
    """Logout the current User"""
    self.endpoints.deleteAccessToken()

read_notifications

read_notifications() -> list[Notification]

Read all Notifications for the current User

Source code in src/plankapy/v2/interface.py
298
299
300
301
@model_list
def read_notifications(self) -> list[Notification]:
    """Read all Notifications for the current User"""
    return [Notification(n, self) for n in self.endpoints.readAllNotifications()['items']]

update_smtp_config

update_smtp_config(**opts: Unpack[Request_updateConfig])

Update the server SMTP config (all args are optional and only passed args will be updated)

PARAMETER DESCRIPTION
smtpHost

Hostname or IP address of the SMTP server

smtpPort

Port number of the SMTP server

smtpName

Client hostname used in the EHLO command for SMTP

smtpSecure

Whether to use a secure connection for SMTP

smtpTlsRejectUnauthorized

Whether to reject unauthorized or self-signed TLS certificates for SMTP connections

smtpUser

Username for authenticating with the SMTP server

smtpPassword

Password for authenticating with the SMTP server

smtpFrom

Default "from" used for outgoing SMTP emails

Source code in src/plankapy/v2/interface.py
245
246
247
248
249
250
251
252
253
254
255
256
257
258
def update_smtp_config(self, **opts: Unpack[typ.Request_updateConfig]):
    """Update the server SMTP config (all args are optional and only passed args will be updated)

    Args:
        smtpHost: Hostname or IP address of the SMTP server
        smtpPort: Port number of the SMTP server
        smtpName: Client hostname used in the EHLO command for SMTP
        smtpSecure: Whether to use a secure connection for SMTP
        smtpTlsRejectUnauthorized: Whether to reject unauthorized or self-signed TLS certificates for SMTP connections
        smtpUser: Username for authenticating with the SMTP server
        smtpPassword: Password for authenticating with the SMTP server
        smtpFrom: Default "from" used for outgoing SMTP emails
    """
    self.endpoints.updateConfig(**opts)