Python SDK: API Reference

Client Classes

Keito

from keito import Keito

client = Keito(
    api_key: str = None,        # defaults to KEITO_API_KEY env var
    account_id: str = None,     # defaults to KEITO_ACCOUNT_ID env var
    base_url: str = "https://api.keito.ai/v1",
    max_retries: int = 2,
    timeout: float = 30.0,
)

AsyncKeito

from keito import AsyncKeito

client = AsyncKeito(
    # Same parameters as Keito
)

Time Entries

client.time_entries.create()

entry = client.time_entries.create(
    project_id: str,            # required
    spent_date: str,            # required, YYYY-MM-DD
    hours: float = 0,           # required unless is_running=True
    task_id: str = None,
    notes: str = None,
    is_running: bool = False,
    is_billable: bool = None,   # defaults from project
    source: str = "api",
    metadata: dict = None,      # max 4KB
) -> TimeEntry

client.time_entries.list()

entries = client.time_entries.list(
    source: str = None,
    project_id: str = None,
    user_id: str = None,
    from_date: str = None,      # YYYY-MM-DD
    to_date: str = None,        # YYYY-MM-DD
    is_running: bool = None,
    cursor: str = None,
    limit: int = 50,            # max 200
) -> PaginatedResponse[TimeEntry]

client.time_entries.get()

entry = client.time_entries.get(id: str) -> TimeEntry

client.time_entries.update()

entry = client.time_entries.update(
    id: str,
    hours: float = None,
    notes: str = None,
    is_running: bool = None,
    is_billable: bool = None,
    task_id: str = None,
    metadata: dict = None,
) -> TimeEntry

client.time_entries.delete()

client.time_entries.delete(id: str) -> None

Expenses

client.expenses.create()

expense = client.expenses.create(
    project_id: str,            # required
    expense_category_id: str,   # required
    spent_date: str,            # required, YYYY-MM-DD
    total_cost: float = None,   # auto-calculated if units + unit_price
    units: float = None,
    unit_price: float = None,
    notes: str = None,
    source: str = "api",
    metadata: dict = None,
) -> Expense

client.expenses.list()

expenses = client.expenses.list(
    source: str = None,
    project_id: str = None,
    user_id: str = None,
    from_date: str = None,
    to_date: str = None,
    cursor: str = None,
    limit: int = 50,
) -> PaginatedResponse[Expense]

client.expenses.get()

expense = client.expenses.get(id: str) -> Expense

Projects

client.projects.list()

projects = client.projects.list(
    cursor: str = None,
    limit: int = 50,
) -> PaginatedResponse[Project]

client.projects.get()

project = client.projects.get(id: str) -> Project

Types

TimeEntry

FieldTypeDescription
idstrUnique identifier
project_idstrProject ID
task_idstr or NoneTask ID
user_idstrUser ID
spent_datestrDate (YYYY-MM-DD)
hoursfloatDuration in hours
notesstr or NoneDescription
is_runningboolTimer active
is_billableboolBillable status
sourcestrOrigin
metadatadict or NoneAgent context
created_atstrISO timestamp
updated_atstrISO timestamp

Expense

FieldTypeDescription
idstrUnique identifier
project_idstrProject ID
expense_category_idstrCategory ID
spent_datestrDate (YYYY-MM-DD)
unitsfloat or NoneQuantity
unit_pricefloat or NonePrice per unit
total_costfloatTotal amount
notesstr or NoneDescription
sourcestrOrigin
metadatadict or NoneAgent context
created_atstrISO timestamp

PaginatedResponse

FieldTypeDescription
datalistArray of results
next_cursorstr or NoneCursor for next page
has_moreboolWhether more results exist