Bulk-importing data (users, teams, projects, bookings, ...) into decidalo
DecidaloAppClient (App Client)
App API (api.decidalo.app)
Reading data from decidalo: searching people, viewing profiles, skills, certificates, projects
Use the Import Client when you need to push data into decidalo (e.g. syncing users from an HR system).
Use the App Client when you need to read data from decidalo (e.g. finding people with specific skills).
Installation
pipinstalldecidalo-client
Import Client (DecidaloClient)
The Import Client wraps the decidalo V3 Import API (Swagger UI).
It is used for bulk-importing data into decidalo using an API key.
importasynciofromdecidalo_clientimportDecidaloClient,DecidaloAPIError,DecidaloAuthenticationErrorasyncdefmain()->None:asyncwithDecidaloClient(api_key="your-api-key")asclient:# Get all usersusers=awaitclient.get_users()foruserinusers:print(f"{user.displayName} ({user.email})")# Get all projectsprojects=awaitclient.get_all_projects()forprojectinprojects:print(f"{project.properties.name.value}")if__name__=="__main__":asyncio.run(main())
Type-safe request/response models using pydantic, generated from the OpenAPI spec of the Import API
Every public method of DecidaloClient wraps exactly one API operation (see API Coverage): path, query parameters, request body and response type follow the spec, and the keyword arguments are the snake_case names of the query parameters (e.g. created_on_or_after for CreatedOnOrAfter)
Query parameters of format date take a datetime.date, those of format date-time a timezone-aware datetime.datetime (annotated as pydantic's AwareDatetime; a naive datetime raises ValueError)
Fields the models don't know (e.g. fields the API added to a response) are ignored instead of failing the validation
The App Client wraps the decidalo App API (api.decidalo.app).
It is used for reading data from decidalo — searching for people, viewing profiles, exploring skills, certificates, and projects.
Authentication
The App Client authenticates via OAuth2 (Microsoft SSO) through login.decidalo.app.
There are two authentication flows:
Device Code Flow (interactive, for first-time setup) — prints a URL and code to the console for you to open in a browser.
Refresh Token Flow (headless, for automation) — reuses a previously obtained refresh token.
importasynciofromdecidalo_app_clientimportDecidaloAppClientfromdecidalo_app_client.authimportDecidaloAuthasyncdeffirst_time_login()->None:"""Interactive login — run this once to obtain a refresh token."""token=awaitDecidaloAuth.device_code_login()# The device code flow prints a URL and code to the console.# Open the URL in your browser and enter the code to authenticate.print(f"Save this refresh token for future use: {token.refresh_token}")asyncio.run(first_time_login())
Store the refresh token securely (e.g. in an environment variable or a secrets manager).
For subsequent runs, use the refresh token:
importasynciofromdecidalo_app_clientimportDecidaloAppClientfromdecidalo_app_client.authimportDecidaloAuthasyncdefmain()->None:# Use a refresh token obtained from a previous device_code_login()token=awaitDecidaloAuth.refresh("your-saved-refresh-token")asyncwithDecidaloAppClient(token=token)asclient:# Search for people with specific skillsresults=awaitclient.search.find_people(keywords=["SAP","Python"])foruserinresults.usersWithMatchedQualities:print(f"User {user.userId} (Score: {user.score})")# Get a user's profile headerheader=awaitclient.profile.get_header(user_id=42)print(f"Profile quality: {header.profileQuality}, last edited by: {header.lastEditor}")# Browse available skill categoriescategories=awaitclient.skills.get_categories()forcatincategories:print(f"Category: {cat.categoryName}")asyncio.run(main())
You can also pass a static Bearer token string directly if you manage tokens yourself:
Then run the tests: unittests/test_models.py checks that the models match the spec, and unittests/test_api_coverage.py checks the API Coverage section of this README against the spec and the client.
To print the expected content of that section, run:
The GitHub source repository was provided by the project maintainers and verified by PyPI at the time of upload. Stars, forks, and open issues/PRs are derived from that repository and have not been independently verified.