An extension to the excellent requests Session object, providing a more straightforward interface for the MicroStrategy REST API.
Requires Python 3.10 or later.
pip install mstr-rest-requestsTo use the built-in credential providers, install the corresponding extra:
pip install mstr-rest-requests[aws] # AWS Secrets Manager & SSM Parameter Store
pip install mstr-rest-requests[azure] # Azure Key Vault
pip install mstr-rest-requests[gcp] # Google Cloud Secret Managerfrom mstr.requests import AuthenticatedMSTRRESTSession
with AuthenticatedMSTRRESTSession(
base_url="https://demo.microstrategy.com/MicroStrategyLibrary/api/",
username="dave",
password="hellodave",
) as session:
projects = session.get("projects").json()The session automatically logs in when the context manager is entered and logs out when it exits.
Four authentication modes are supported. In every case you can use either the context-manager style shown above or the manual approach shown below.
from mstr.requests import MSTRRESTSession
session = MSTRRESTSession(
base_url="https://demo.microstrategy.com/MicroStrategyLibrary/api/"
)
session.login(username="dave", password="hellodave")Context manager:
with AuthenticatedMSTRRESTSession(
base_url="https://.../api/",
identity_token="supersecretidentitytoken",
) as session:
...Manual:
session.delegate(identity_token="supersecretidentitytoken")Context manager (use the api_key parameter; supports callables for vaults):
with AuthenticatedMSTRRESTSession(
base_url="https://.../api/",
api_key="your-api-key",
) as session:
...Manual:
session.login(api_key="your-api-key")Context manager:
with AuthenticatedMSTRRESTSession(base_url="https://.../api/") as session:
...Manual:
session.login()Every credential parameter on AuthenticatedMSTRRESTSession -- including
base_url -- accepts either a plain string or a zero-argument callable
that returns a string (the :data:Credential type). Callables are resolved
lazily when the context manager is entered, not when the session is constructed.
You can import the type alias from mstr.requests for type hints.
This makes it easy to pull credentials from vaults, environment helpers, or any other source at connect time:
from mstr.requests import AuthenticatedMSTRRESTSession
with AuthenticatedMSTRRESTSession(
base_url="https://demo.microstrategy.com/MicroStrategyLibrary/api/",
username=lambda: get_username_from_somewhere(),
password=lambda: get_password_from_somewhere(),
) as session:
...Install with pip install mstr-rest-requests[aws].
Use secrets_manager to create a callable for a single secret value:
from mstr.requests import AuthenticatedMSTRRESTSession
from mstr.requests.credentials.aws import secrets_manager
with AuthenticatedMSTRRESTSession(
base_url="https://demo.microstrategy.com/MicroStrategyLibrary/api/",
username=secrets_manager("my-secret-id", key="username"),
password=secrets_manager("my-secret-id", key="password"),
) as session:
...When a single secret contains all connection details as a JSON object, use
SecretsManagerSecret to fetch the secret once and share it across fields:
from mstr.requests import AuthenticatedMSTRRESTSession
from mstr.requests.credentials.aws import SecretsManagerSecret
secret = SecretsManagerSecret("my-secret-id")
with AuthenticatedMSTRRESTSession(
base_url=secret.field("base_url"),
username=secret.field("username"),
password=secret.field("password"),
) as session:
...The secret is only fetched on the first field resolution, and the result is cached for all subsequent fields.
Also covered by the aws extra (pip install mstr-rest-requests[aws]).
from mstr.requests.credentials.aws import parameter_store
with AuthenticatedMSTRRESTSession(
base_url=parameter_store("/myapp/mstr/base_url"),
username=parameter_store("/myapp/mstr/username"),
password=parameter_store("/myapp/mstr/password"),
) as session:
...ParameterStoreValues caches each parameter after the first fetch so
repeated resolutions of the same name do not make extra API calls:
from mstr.requests.credentials.aws import ParameterStoreValues
params = ParameterStoreValues()
with AuthenticatedMSTRRESTSession(
base_url=params.parameter("/myapp/mstr/base_url"),
username=params.parameter("/myapp/mstr/username"),
password=params.parameter("/myapp/mstr/password"),
) as session:
...Install with pip install mstr-rest-requests[azure]. Authentication uses
DefaultAzureCredential
which supports managed identity, environment variables, Azure CLI, and more.
from mstr.requests.credentials.azure import key_vault
with AuthenticatedMSTRRESTSession(
base_url="https://demo.microstrategy.com/MicroStrategyLibrary/api/",
username=key_vault("https://my-vault.vault.azure.net/", "mstr-username"),
password=key_vault("https://my-vault.vault.azure.net/", "mstr-password"),
) as session:
...from mstr.requests.credentials.azure import KeyVaultSecret
secret = KeyVaultSecret("https://my-vault.vault.azure.net/", "mstr-connection")
with AuthenticatedMSTRRESTSession(
base_url=secret.field("base_url"),
username=secret.field("username"),
password=secret.field("password"),
) as session:
...Install with pip install mstr-rest-requests[gcp]. Authentication uses
Application Default Credentials.
from mstr.requests.credentials.gcp import secret_manager
with AuthenticatedMSTRRESTSession(
base_url="https://demo.microstrategy.com/MicroStrategyLibrary/api/",
username=secret_manager("my-project", "mstr-username"),
password=secret_manager("my-project", "mstr-password"),
) as session:
...from mstr.requests.credentials.gcp import SecretManagerSecret
secret = SecretManagerSecret("my-project", "mstr-connection")
with AuthenticatedMSTRRESTSession(
base_url=secret.field("base_url"),
username=secret.field("username"),
password=secret.field("password"),
) as session:
...session.has_session() # True if an auth token is present
session.get_session_info() # GET /sessions
session.extend_session() # PUT /sessions (prolongs the session)
session.get_userinfo() # GET /sessions/userInfoA session can be serialised to JSON and later restored, which is useful for passing sessions between processes:
data = session.json()
# Later, in another process:
restored = MSTRRESTSession.from_dict(json.loads(data))session.load_projects()
project_id = session.get_project_id("My Project")
response = session.get("reports/abc123", project_id=project_id)MSTRRESTSession extends requests.Session, so the full requests API is
available. Two extra keyword arguments are added to every request method:
include_auth(defaultTrue) -- attach theX-MSTR-AuthTokenheader.project_id-- attach theX-MSTR-ProjectIDheader for project-scoped endpoints.
response = session.get("reports/abc123", project_id="B7CA92...")All API error responses are translated into typed exceptions:
| Exception | Error codes | Trigger |
|---|---|---|
LoginFailureException |
ERR003 | Authentication error |
IServerException |
ERR002, ERR0013 | IServer error or unreachable |
ResourceNotFoundException |
ERR004 | Resource not found |
InvalidRequestException |
ERR005, ERR006, ERR007 | Missing or invalid input |
SessionException |
ERR009 | Session invalid or timed out |
InsufficientPrivilegesException |
ERR0014, ERR0017 | Insufficient privileges / permission |
ObjectAlreadyExistsException |
ERR0015 | Object already exists |
ExecutionCancelledException |
-- | Report or cube execution cancelled |
MSTRUnknownException |
-- | Response missing error code |
MSTRException |
Everything else | Base class / catch-all |
from mstr.requests.rest.exceptions import LoginFailureExceptionApache 2.0 -- see LICENSE for details.