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
| Field | Type | Description |
|---|
id | str | Unique identifier |
project_id | str | Project ID |
task_id | str or None | Task ID |
user_id | str | User ID |
spent_date | str | Date (YYYY-MM-DD) |
hours | float | Duration in hours |
notes | str or None | Description |
is_running | bool | Timer active |
is_billable | bool | Billable status |
source | str | Origin |
metadata | dict or None | Agent context |
created_at | str | ISO timestamp |
updated_at | str | ISO timestamp |
Expense
| Field | Type | Description |
|---|
id | str | Unique identifier |
project_id | str | Project ID |
expense_category_id | str | Category ID |
spent_date | str | Date (YYYY-MM-DD) |
units | float or None | Quantity |
unit_price | float or None | Price per unit |
total_cost | float | Total amount |
notes | str or None | Description |
source | str | Origin |
metadata | dict or None | Agent context |
created_at | str | ISO timestamp |
PaginatedResponse
| Field | Type | Description |
|---|
data | list | Array of results |
next_cursor | str or None | Cursor for next page |
has_more | bool | Whether more results exist |