inMotion Python SDK

 1from inmotion.api import (
 2    InMotionSession,
 3    InMotionAccounts,
 4    InMotionActivities,
 5    InMotionActivityConfig,
 6    InMotionApiKeys,
 7    InMotionAudit,
 8    InMotionDataStream,
 9    InMotionDatasets,
10    InMotionDevKeys,
11    InMotionEvents,
12    InMotionExplorer,
13    InMotionFolio,
14    InMotionModel,
15    InMotionMqttDeployment,
16    InMotionShape,
17    InMotionShapeGenerator,
18    InMotionUpload,
19    InMotionUser,
20)
21
22__all__ = [
23    "InMotionSession",
24    "InMotionAccounts",
25    "InMotionActivities",
26    "InMotionActivityConfig",
27    "InMotionApiKeys",
28    "InMotionAudit",
29    "InMotionDataStream",
30    "InMotionDatasets",
31    "InMotionDevKeys",
32    "InMotionEvents",
33    "InMotionExplorer",
34    "InMotionFolio",
35    "InMotionModel",
36    "InMotionMqttDeployment",
37    "InMotionShape",
38    "InMotionShapeGenerator",
39    "InMotionUpload",
40    "InMotionUser",
41]
class InMotionSession(abc.ABC):
2850class InMotionSession(ABC):
2851    @abstractmethod
2852    def disconnect(self) -> None:
2853        """ Disconnect the session """
2854        pass
2855
2856    @abstractmethod
2857    def activities(self) -> InMotionActivities:
2858        """ Retrieve the activities interface for the session
2859
2860        :return: The activities interface
2861        :rtype: InMotionActivities
2862        """
2863        pass
2864
2865    @abstractmethod
2866    def accounts(self) -> InMotionAccounts:
2867        """ Retrieve the account management interface for the session
2868
2869        :return: The account management interface
2870        :rtype: InMotionAccounts
2871        """
2872        pass
2873
2874    @abstractmethod
2875    def events(self) -> InMotionEvents:
2876        """ Retrieve the event management interface for the session
2877
2878        :return: The event management interface
2879        :rtype: InMotionEvents
2880        """
2881        pass
2882
2883    @abstractmethod
2884    def dev_keys(self) -> InMotionDevKeys:
2885        """ Retrieve the developer key management interface for the session
2886
2887        :return: The developer key management interface
2888        :rtype: InMotionDevKeys
2889        """
2890        pass
2891
2892    @abstractmethod
2893    def api_keys(self) -> InMotionApiKeys:
2894        """ Retrieve the API key management interface for the session
2895
2896        :return: The API key management interface
2897        :rtype: InMotionApiKeys
2898        """
2899        pass
2900
2901    @abstractmethod
2902    def user(self) -> InMotionUser:
2903        """ Retrieve the user management interface for the session
2904
2905        :return: The user management interface
2906        :rtype: InMotionUser
2907        """
2908        pass
2909
2910    @abstractmethod
2911    def activity_config(self) -> InMotionActivityConfig:
2912        """ Retrieve the activity configuration interface for the session
2913
2914        :return: The activity configuration interface
2915        :rtype: InMotionActivityConfig
2916        """
2917        pass
2918
2919    @abstractmethod
2920    def upload(self) -> InMotionUpload:
2921        """ Retrieve the upload management interface for the session
2922
2923        :return: The upload management interface
2924        :rtype: InMotionUpload
2925        """
2926        pass
2927
2928    @abstractmethod
2929    def folio(self) -> InMotionFolio:
2930        """ Retrieve the folio management interface for the session
2931
2932        :return: The folio management interface
2933        :rtype: InMotionFolio
2934        """
2935        pass
2936
2937    @abstractmethod
2938    def data_stream(self) -> InMotionDataStream:
2939        """ Retrieve the data stream management interface for the session
2940
2941        :return: The data stream management interface
2942        :rtype: InMotionDataStream
2943        """
2944        pass
2945
2946    @abstractmethod
2947    def shape(self) -> InMotionShape:
2948        """ Retrieve the shape management interface for the session
2949
2950        :return: The shape management interface
2951        :rtype: InMotionShape
2952        """
2953        pass
2954
2955    @abstractmethod
2956    def datasets(self) -> InMotionDatasets:
2957        """ Retrieve the gridded dataset interface for the session
2958
2959        :return: The dataset interface
2960        :rtype: InMotionDatasets
2961        """
2962        pass
2963
2964    @abstractmethod
2965    def explorer(self) -> InMotionExplorer:
2966        """ Retrieve the Explorer catalog interface for the session
2967
2968        :return: The Explorer catalog interface
2969        :rtype: InMotionExplorer
2970        """
2971        pass
2972
2973    @abstractmethod
2974    def shape_generator(self) -> InMotionShapeGenerator:
2975        """ Retrieve the shape generator management interface for the session
2976
2977        :return: The shape generator management interface
2978        :rtype: InMotionShapeGenerator
2979        """
2980        pass
2981
2982    @abstractmethod
2983    def audit(self) -> InMotionAudit:
2984        """ Retrieve the external audit interface for the session
2985
2986        :return: The external audit interface
2987        :rtype: InMotionAudit
2988        """
2989        pass
2990
2991    @abstractmethod
2992    def model(self) -> InMotionModel:
2993        """ Retrieve the model catalogue interface for the session
2994
2995        :return: The model catalogue interface
2996        :rtype: InMotionModel
2997        """
2998        pass
2999
3000    @abstractmethod
3001    def mqtt_deployment(self) -> InMotionMqttDeployment:
3002        """ Retrieve the MQTT ingestion deployment interface for the session
3003
3004        :return: The MQTT ingestion deployment interface
3005        :rtype: InMotionMqttDeployment
3006        """
3007        pass
3008
3009    @property
3010    @abstractmethod
3011    def is_connected(self) -> bool:
3012        """ Determine if the session is connected
3013
3014        :return: True if the session is connected, False otherwise
3015        :rtype: bool
3016        """
3017        pass
3018
3019    @property
3020    @abstractmethod
3021    def base_url(self) -> str:
3022        """ The base URL for the inMotion instance
3023
3024        :return: The base URL
3025        :rtype: str
3026        """
3027        pass
3028
3029    @property
3030    @abstractmethod
3031    def api_path(self) -> str:
3032        """ The API path for the inMotion instance
3033
3034        :return: The API path
3035        :rtype: str
3036        """
3037        pass
3038
3039    @property
3040    @abstractmethod
3041    def account(self) -> str:
3042        """ The account associated with the session
3043
3044        :return: The account
3045        :rtype: str
3046        """
3047        pass
3048
3049    @abstractmethod
3050    def build_headers(self, content: str) -> dict[str, str]:
3051        """ Build the headers for a request to inMotion
3052
3053        :param str content: The content to be sent in the request
3054        :return: The headers for the request
3055        :rtype: dict[str, str]
3056        """
3057        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def disconnect(self) -> None:
2851    @abstractmethod
2852    def disconnect(self) -> None:
2853        """ Disconnect the session """
2854        pass

Disconnect the session

@abstractmethod
def activities(self) -> InMotionActivities:
2856    @abstractmethod
2857    def activities(self) -> InMotionActivities:
2858        """ Retrieve the activities interface for the session
2859
2860        :return: The activities interface
2861        :rtype: InMotionActivities
2862        """
2863        pass

Retrieve the activities interface for the session

Returns

The activities interface

@abstractmethod
def accounts(self) -> InMotionAccounts:
2865    @abstractmethod
2866    def accounts(self) -> InMotionAccounts:
2867        """ Retrieve the account management interface for the session
2868
2869        :return: The account management interface
2870        :rtype: InMotionAccounts
2871        """
2872        pass

Retrieve the account management interface for the session

Returns

The account management interface

@abstractmethod
def events(self) -> InMotionEvents:
2874    @abstractmethod
2875    def events(self) -> InMotionEvents:
2876        """ Retrieve the event management interface for the session
2877
2878        :return: The event management interface
2879        :rtype: InMotionEvents
2880        """
2881        pass

Retrieve the event management interface for the session

Returns

The event management interface

@abstractmethod
def dev_keys(self) -> InMotionDevKeys:
2883    @abstractmethod
2884    def dev_keys(self) -> InMotionDevKeys:
2885        """ Retrieve the developer key management interface for the session
2886
2887        :return: The developer key management interface
2888        :rtype: InMotionDevKeys
2889        """
2890        pass

Retrieve the developer key management interface for the session

Returns

The developer key management interface

@abstractmethod
def api_keys(self) -> InMotionApiKeys:
2892    @abstractmethod
2893    def api_keys(self) -> InMotionApiKeys:
2894        """ Retrieve the API key management interface for the session
2895
2896        :return: The API key management interface
2897        :rtype: InMotionApiKeys
2898        """
2899        pass

Retrieve the API key management interface for the session

Returns

The API key management interface

@abstractmethod
def user(self) -> InMotionUser:
2901    @abstractmethod
2902    def user(self) -> InMotionUser:
2903        """ Retrieve the user management interface for the session
2904
2905        :return: The user management interface
2906        :rtype: InMotionUser
2907        """
2908        pass

Retrieve the user management interface for the session

Returns

The user management interface

@abstractmethod
def activity_config(self) -> InMotionActivityConfig:
2910    @abstractmethod
2911    def activity_config(self) -> InMotionActivityConfig:
2912        """ Retrieve the activity configuration interface for the session
2913
2914        :return: The activity configuration interface
2915        :rtype: InMotionActivityConfig
2916        """
2917        pass

Retrieve the activity configuration interface for the session

Returns

The activity configuration interface

@abstractmethod
def upload(self) -> InMotionUpload:
2919    @abstractmethod
2920    def upload(self) -> InMotionUpload:
2921        """ Retrieve the upload management interface for the session
2922
2923        :return: The upload management interface
2924        :rtype: InMotionUpload
2925        """
2926        pass

Retrieve the upload management interface for the session

Returns

The upload management interface

@abstractmethod
def folio(self) -> InMotionFolio:
2928    @abstractmethod
2929    def folio(self) -> InMotionFolio:
2930        """ Retrieve the folio management interface for the session
2931
2932        :return: The folio management interface
2933        :rtype: InMotionFolio
2934        """
2935        pass

Retrieve the folio management interface for the session

Returns

The folio management interface

@abstractmethod
def data_stream(self) -> InMotionDataStream:
2937    @abstractmethod
2938    def data_stream(self) -> InMotionDataStream:
2939        """ Retrieve the data stream management interface for the session
2940
2941        :return: The data stream management interface
2942        :rtype: InMotionDataStream
2943        """
2944        pass

Retrieve the data stream management interface for the session

Returns

The data stream management interface

@abstractmethod
def shape(self) -> InMotionShape:
2946    @abstractmethod
2947    def shape(self) -> InMotionShape:
2948        """ Retrieve the shape management interface for the session
2949
2950        :return: The shape management interface
2951        :rtype: InMotionShape
2952        """
2953        pass

Retrieve the shape management interface for the session

Returns

The shape management interface

@abstractmethod
def datasets(self) -> InMotionDatasets:
2955    @abstractmethod
2956    def datasets(self) -> InMotionDatasets:
2957        """ Retrieve the gridded dataset interface for the session
2958
2959        :return: The dataset interface
2960        :rtype: InMotionDatasets
2961        """
2962        pass

Retrieve the gridded dataset interface for the session

Returns

The dataset interface

@abstractmethod
def explorer(self) -> InMotionExplorer:
2964    @abstractmethod
2965    def explorer(self) -> InMotionExplorer:
2966        """ Retrieve the Explorer catalog interface for the session
2967
2968        :return: The Explorer catalog interface
2969        :rtype: InMotionExplorer
2970        """
2971        pass

Retrieve the Explorer catalog interface for the session

Returns

The Explorer catalog interface

@abstractmethod
def shape_generator(self) -> InMotionShapeGenerator:
2973    @abstractmethod
2974    def shape_generator(self) -> InMotionShapeGenerator:
2975        """ Retrieve the shape generator management interface for the session
2976
2977        :return: The shape generator management interface
2978        :rtype: InMotionShapeGenerator
2979        """
2980        pass

Retrieve the shape generator management interface for the session

Returns

The shape generator management interface

@abstractmethod
def audit(self) -> InMotionAudit:
2982    @abstractmethod
2983    def audit(self) -> InMotionAudit:
2984        """ Retrieve the external audit interface for the session
2985
2986        :return: The external audit interface
2987        :rtype: InMotionAudit
2988        """
2989        pass

Retrieve the external audit interface for the session

Returns

The external audit interface

@abstractmethod
def model(self) -> InMotionModel:
2991    @abstractmethod
2992    def model(self) -> InMotionModel:
2993        """ Retrieve the model catalogue interface for the session
2994
2995        :return: The model catalogue interface
2996        :rtype: InMotionModel
2997        """
2998        pass

Retrieve the model catalogue interface for the session

Returns

The model catalogue interface

@abstractmethod
def mqtt_deployment(self) -> InMotionMqttDeployment:
3000    @abstractmethod
3001    def mqtt_deployment(self) -> InMotionMqttDeployment:
3002        """ Retrieve the MQTT ingestion deployment interface for the session
3003
3004        :return: The MQTT ingestion deployment interface
3005        :rtype: InMotionMqttDeployment
3006        """
3007        pass

Retrieve the MQTT ingestion deployment interface for the session

Returns

The MQTT ingestion deployment interface

is_connected: bool
3009    @property
3010    @abstractmethod
3011    def is_connected(self) -> bool:
3012        """ Determine if the session is connected
3013
3014        :return: True if the session is connected, False otherwise
3015        :rtype: bool
3016        """
3017        pass

Determine if the session is connected

Returns

True if the session is connected, False otherwise

base_url: str
3019    @property
3020    @abstractmethod
3021    def base_url(self) -> str:
3022        """ The base URL for the inMotion instance
3023
3024        :return: The base URL
3025        :rtype: str
3026        """
3027        pass

The base URL for the inMotion instance

Returns

The base URL

api_path: str
3029    @property
3030    @abstractmethod
3031    def api_path(self) -> str:
3032        """ The API path for the inMotion instance
3033
3034        :return: The API path
3035        :rtype: str
3036        """
3037        pass

The API path for the inMotion instance

Returns

The API path

account: str
3039    @property
3040    @abstractmethod
3041    def account(self) -> str:
3042        """ The account associated with the session
3043
3044        :return: The account
3045        :rtype: str
3046        """
3047        pass

The account associated with the session

Returns

The account

@abstractmethod
def build_headers(self, content: str) -> dict[str, str]:
3049    @abstractmethod
3050    def build_headers(self, content: str) -> dict[str, str]:
3051        """ Build the headers for a request to inMotion
3052
3053        :param str content: The content to be sent in the request
3054        :return: The headers for the request
3055        :rtype: dict[str, str]
3056        """
3057        pass

Build the headers for a request to inMotion

Parameters
  • str content: The content to be sent in the request
Returns

The headers for the request

class InMotionAccounts(abc.ABC):
 706class InMotionAccounts(ABC):
 707    @abstractmethod
 708    def find_account(self, account_key: str) -> AccountDetailsModel:
 709        """ Find an account by its unique key
 710
 711        :param str account_key: The unique key of the account
 712        :return: The account details
 713        :rtype: AccountDetailsModel
 714        """
 715        pass
 716
 717    @abstractmethod
 718    def find_account_tags(self, account_key: str) -> AccountTagsModel:
 719        """ Find the tags associated with an account
 720
 721        :param str account_key: The unique key of the account
 722        :return: The account's tags
 723        :rtype: AccountTagsModel
 724        """
 725        pass
 726
 727    @abstractmethod
 728    def update_account(self, account_key: str, account: AccountModel) -> AccountDetailsModel:
 729        """ Update the details of an existing account
 730
 731        :param str account_key: The unique key of the account to update
 732        :param AccountModel account: The updated account definition
 733        :return: The updated account details
 734        :rtype: AccountDetailsModel
 735        """
 736        pass
 737
 738    @abstractmethod
 739    def find_account_users(self, account_key: str) -> list[AccountUserSummaryModel]:
 740        """ Retrieve the users associated with an account
 741
 742        :param str account_key: The unique key of the account
 743        :return: The users linked to the account
 744        :rtype: list[AccountUserSummaryModel]
 745        """
 746        pass
 747
 748    @abstractmethod
 749    def register_account_user(self, account_key: str, user_key: str, privileges: AccountPrivilegesModel) -> list[AccountUserSummaryModel]:
 750        """ Register a user to an account
 751
 752        :param str account_key: The unique key of the account
 753        :param str user_key: The unique key of the user to register
 754        :param AccountPrivilegesModel privileges: The privileges to grant the user on the account
 755        :return: The users linked to the account after registration
 756        :rtype: list[AccountUserSummaryModel]
 757        """
 758        pass
 759
 760    @abstractmethod
 761    def unregister_account_user(self, account_key: str, user_key: str) -> AccountUserUnregisteredModel:
 762        """ Unregister a user from an account
 763
 764        :param str account_key: The unique key of the account
 765        :param str user_key: The unique key of the user to unregister
 766        :return: The result of the unregister operation
 767        :rtype: AccountUserUnregisteredModel
 768        """
 769        pass
 770
 771    @abstractmethod
 772    def batch_update_account_users(self, account_key: str, commands: list[AccountUpdateBatchCommandModel]) -> AccountUpdateBatchResultsModel:
 773        """ Apply a batch of register, unregister, or update actions to the users of an account
 774
 775        :param str account_key: The unique key of the account
 776        :param list[AccountUpdateBatchCommandModel] commands: The batch of commands to apply
 777        :return: The results of the batch update
 778        :rtype: AccountUpdateBatchResultsModel
 779        """
 780        pass
 781
 782    @abstractmethod
 783    def create_account_only(self, account: AccountModel) -> AccountDetailsModel:
 784        """ Create a new free personal account that is not yet associated with any user
 785
 786        :param AccountModel account: The definition of the account to create
 787        :return: The created account's details
 788        :rtype: AccountDetailsModel
 789        """
 790        pass
 791
 792    @abstractmethod
 793    def request_account_data(self, account_key: str) -> StatusMessageModel:
 794        """ Request a copy of all the account's data, which is prepared and sent to the owner.
 795        Limited to a few requests per day.
 796
 797        :param str account_key: The unique key of the account (the caller must own it)
 798        :return: The status of the request
 799        :rtype: StatusMessageModel
 800        """
 801        pass
 802
 803    @abstractmethod
 804    def mark_account_for_deletion(self, account_key: str, and_user: bool) -> AccountMarkedForDeletionModel:
 805        """ Mark an account for deletion
 806
 807        :param str account_key: The unique key of the account to mark for deletion
 808        :param bool and_user: Whether the associated user should also be marked for deletion
 809        :return: The result of the mark-for-deletion operation
 810        :rtype: AccountMarkedForDeletionModel
 811        """
 812        pass
 813
 814    @abstractmethod
 815    def find_my_accounts(self) -> list[UserAccountSummaryModel]:
 816        """ Fetch the accounts associated with the authenticated user
 817
 818        :return: The caller's summary of each account
 819        :rtype: list[UserAccountSummaryModel]
 820        """
 821        pass
 822
 823    @abstractmethod
 824    def fetch_global_device_configs(self) -> dict:
 825        """ Fetch the system-wide default Device Configs (global tier), for runtime consumers to
 826        merge with an account's own tier themselves - never merged here. Not account-scoped.
 827
 828        :return: A raw dict shaped `{ deviceConfigs: [{name, version, yaml}] }`
 829        :rtype: dict
 830        """
 831        pass
 832
 833    @abstractmethod
 834    def sync_device_configs(self, request: DeviceConfigSyncRequestModel) -> DeviceConfigSyncResultModel:
 835        """ Fetch only the Device Config changes (global tier and a set of accounts) since a
 836        given time, in one call
 837
 838        :param DeviceConfigSyncRequestModel request: The sync window and accounts to include
 839        :return: The delta - entries changed since `since`, plus tombstones
 840        :rtype: DeviceConfigSyncResultModel
 841        """
 842        pass
 843
 844    @abstractmethod
 845    def add_account_member(self, account_key: str, request: AddAccountMemberRequestModel) -> dict:
 846        """ Add someone to an account by username or email. If the value resolves to an existing inMotion
 847        user they are registered immediately; otherwise (given `consent`) an external invite is sent instead.
 848        Requires account admin.
 849
 850        :param str account_key: The unique key of the account
 851        :param AddAccountMemberRequestModel request: Who to add, the access to grant, and the consent/message
 852            used only if an invite has to be sent
 853        :return: A dict discriminated by `kind` - `"member"` (with `user`, an account user summary) or
 854            `"invite"` (with `invite`, a friend-invite)
 855        :rtype: dict
 856        """
 857        pass
 858
 859    @abstractmethod
 860    def send_friend_invite(self, account_key: str, request: FriendInviteRequestModel) -> FriendInviteModel:
 861        """ Invite someone who is not yet an inMotion user to join an account, by email. Rejected if the
 862        email already belongs to a registered user. Requires account admin; rate limited per address.
 863
 864        :param str account_key: The unique key of the account
 865        :param FriendInviteRequestModel request: The email to invite, `consent` (must be true) and an
 866            optional personal note (max 200 characters)
 867        :return: The created invite
 868        :rtype: FriendInviteModel
 869        """
 870        pass
 871
 872    @abstractmethod
 873    def list_friend_invites(self, account_key: str) -> list[FriendInviteModel]:
 874        """ List the friend-invites sent from an account. Requires account admin.
 875
 876        :param str account_key: The unique key of the account
 877        :return: The account's invites, whatever their status
 878        :rtype: list[FriendInviteModel]
 879        """
 880        pass
 881
 882    @abstractmethod
 883    def revoke_friend_invite(self, account_key: str, token: str) -> FriendInviteModel:
 884        """ Cancel a still-pending friend-invite so it can no longer be accepted. No-op if it was already
 885        accepted or revoked. Requires account admin.
 886
 887        :param str account_key: The unique key of the account
 888        :param str token: The invite's token
 889        :return: The invite, as it now stands
 890        :rtype: FriendInviteModel
 891        """
 892        pass
 893
 894    @abstractmethod
 895    def list_activity_types(self, account_key: str) -> list[dict]:
 896        """ List every Activity Type (global and account-scoped custom, each tagged its own `source`)
 897        browsable by an account.
 898
 899        :param str account_key: The unique key of the account
 900        :return: Every Activity Type entry, as raw dicts (no fixed schema is declared server-side)
 901        :rtype: list[dict]
 902        """
 903        pass
 904
 905    @abstractmethod
 906    def find_account_activity_master_data(self, account_key: str) -> dict:
 907        """ Fetch master data (profile types, standard data types and activity types) for an account.
 908        Same shape as `InMotionActivities.find_activity_master_data`, but the activity types are the
 909        account's merged set - the global catalog plus its own custom Activity Types, the account's
 910        winning on a key collision. Readable by any account member.
 911
 912        :param str account_key: The unique key of the account
 913        :return: The account's merged master data, as a raw dict
 914        :rtype: dict
 915        """
 916        pass
 917
 918    @abstractmethod
 919    def create_activity_type(self, account_key: str, yaml_document: str) -> dict:
 920        """ Create an account-scoped custom Activity Type. Requires the "custom-activity-type" account
 921        feature. Fails if the account already has a custom Activity Type at that key.
 922
 923        :param str account_key: The unique key of the account
 924        :param str yaml_document: A standalone single-entry YAML document; its identity is its own `key` field
 925        :return: The created Activity Type entry, as a raw dict
 926        :rtype: dict
 927        """
 928        pass
 929
 930    @abstractmethod
 931    def update_activity_type(self, account_key: str, key: str, yaml_document: str) -> dict:
 932        """ Update an account-scoped custom Activity Type. Requires the "custom-activity-type" account
 933        feature. Fails if none exists yet at `key` (use create_activity_type), or if the document's own
 934        `key` field doesn't match `key`.
 935
 936        :param str account_key: The unique key of the account
 937        :param str key: The key of the custom Activity Type to update
 938        :param str yaml_document: A standalone single-entry YAML document
 939        :return: The updated Activity Type entry, as a raw dict
 940        :rtype: dict
 941        """
 942        pass
 943
 944    @abstractmethod
 945    def delete_activity_type(self, account_key: str, key: str) -> None:
 946        """ Delete an account-scoped custom Activity Type. Idempotent. Requires the "custom-activity-type"
 947        account feature.
 948
 949        :param str account_key: The unique key of the account
 950        :param str key: The key of the custom Activity Type to delete
 951        """
 952        pass
 953
 954    @abstractmethod
 955    def list_standard_data_types(self, account_key: str) -> list[dict]:
 956        """ List every Standard Data Type entry (global and account, each tagged its own
 957        `source`) visible to an account. Requires the "custom-sdt" account feature.
 958
 959        :param str account_key: The unique key of the account
 960        :return: Every Standard Data Type entry, as raw dicts (no fixed schema is declared server-side)
 961        :rtype: list[dict]
 962        """
 963        pass
 964
 965    @abstractmethod
 966    def create_standard_data_type(self, account_key: str, yaml_document: str) -> dict:
 967        """ Create an account-scoped Standard Data Type override. Requires the "custom-sdt"
 968        account feature. Fails if the account already has an override at the document's own
 969        `key`, or the document references an unknown `variant-type`.
 970
 971        :param str account_key: The unique key of the account
 972        :param str yaml_document: A standalone single-entry YAML document; its identity is its own `key` field
 973        :return: The created Standard Data Type entry, as a raw dict
 974        :rtype: dict
 975        """
 976        pass
 977
 978    @abstractmethod
 979    def update_standard_data_type(self, account_key: str, key: str, yaml_document: str) -> dict:
 980        """ Update an account-scoped Standard Data Type override. Fails if no override exists yet
 981        at `key` (use create instead), or if the document's own `key` field doesn't match.
 982        Requires the "custom-sdt" account feature.
 983
 984        :param str account_key: The unique key of the account
 985        :param str key: The key of the Standard Data Type override to update
 986        :param str yaml_document: The replacement standalone single-entry YAML document
 987        :return: The updated Standard Data Type entry, as a raw dict
 988        :rtype: dict
 989        """
 990        pass
 991
 992    @abstractmethod
 993    def delete_standard_data_type(self, account_key: str, key: str) -> None:
 994        """ Delete an account-scoped Standard Data Type override. Idempotent. Requires the
 995        "custom-sdt" account feature.
 996
 997        :param str account_key: The unique key of the account
 998        :param str key: The key of the Standard Data Type override to delete
 999        """
1000        pass
1001
1002    @abstractmethod
1003    def list_standard_data_variant_types(self, account_key: str) -> list[dict]:
1004        """ List every Standard Data Variant Type entry (global and account, each tagged its own
1005        `source`) visible to an account. Requires the "custom-sdt" account feature.
1006
1007        :param str account_key: The unique key of the account
1008        :return: Every Standard Data Variant Type entry, as raw dicts
1009        :rtype: list[dict]
1010        """
1011        pass
1012
1013    @abstractmethod
1014    def create_standard_data_variant_type(self, account_key: str, yaml_document: str) -> dict:
1015        """ Create an account-scoped Standard Data Variant Type override. Requires the
1016        "custom-sdt" account feature. Fails if the account already has an override at the
1017        document's own `key`.
1018
1019        :param str account_key: The unique key of the account
1020        :param str yaml_document: A standalone single-entry YAML document; its identity is its own `key` field
1021        :return: The created Standard Data Variant Type entry, as a raw dict
1022        :rtype: dict
1023        """
1024        pass
1025
1026    @abstractmethod
1027    def update_standard_data_variant_type(self, account_key: str, key: str, yaml_document: str) -> dict:
1028        """ Update an account-scoped Standard Data Variant Type override. Fails if no override
1029        exists yet at `key`, or if the document's own `key` field doesn't match. Requires the
1030        "custom-sdt" account feature.
1031
1032        :param str account_key: The unique key of the account
1033        :param str key: The key of the Standard Data Variant Type override to update
1034        :param str yaml_document: The replacement standalone single-entry YAML document
1035        :return: The updated Standard Data Variant Type entry, as a raw dict
1036        :rtype: dict
1037        """
1038        pass
1039
1040    @abstractmethod
1041    def delete_standard_data_variant_type(self, account_key: str, key: str) -> None:
1042        """ Delete an account-scoped Standard Data Variant Type override. Fails, naming the
1043        referencing Data Type keys, if any of the account's own Data Types currently reference
1044        this variant type. Idempotent otherwise. Requires the "custom-sdt" account feature.
1045
1046        :param str account_key: The unique key of the account
1047        :param str key: The key of the Standard Data Variant Type override to delete
1048        """
1049        pass
1050
1051    @abstractmethod
1052    def fetch_device_configs(self, account_key: str, preview: bool = False) -> dict:
1053        """ Fetch an account's own tier of Device Configs, for runtime consumers to merge with
1054        the global tier themselves - never merged here. Always succeeds with an empty list if
1055        nothing has been published yet.
1056
1057        :param str account_key: The unique key of the account
1058        :param bool preview: If True, serves the in-progress development version per name where
1059            one exists (falling back to published) - restricted to the account's admins/owners
1060        :return: A raw dict shaped `{ deviceConfigs: [{name, version, yaml}] }`
1061        :rtype: dict
1062        """
1063        pass
1064
1065    @abstractmethod
1066    def list_device_configs(self, account_key: str) -> dict:
1067        """ List every version of every one of the account's named Device Configs, for an
1068        editing UI. Requires the "custom-device-config" account feature.
1069
1070        :param str account_key: The unique key of the account
1071        :return: A raw dict shaped `{ deviceConfigs: [...] }`
1072        :rtype: dict
1073        """
1074        pass
1075
1076    @abstractmethod
1077    def create_device_config(self, account_key: str, yaml_document: str) -> dict:
1078        """ Validate and create a brand-new Device Config at version 1, status development.
1079        Requires the "custom-device-config" account feature. Fails if a Device Config with that
1080        name already exists for this account.
1081
1082        :param str account_key: The unique key of the account
1083        :param str yaml_document: The Device Config document; its identity is its own `profile.name` field
1084        :return: The new Device Config's id/version/status/yaml/updatedAt/updatedBy, as a raw dict
1085        :rtype: dict
1086        """
1087        pass
1088
1089    @abstractmethod
1090    def save_device_config(self, account_key: str, name: str, yaml_document: str) -> dict:
1091        """ Validate and save new content to the current development version of a named Device
1092        Config, in place. Requires the "custom-device-config" account feature. Fails if no
1093        development version is in progress.
1094
1095        :param str account_key: The unique key of the account
1096        :param str name: The name of the Device Config
1097        :param str yaml_document: The replacement Device Config document
1098        :return: The updated Device Config version, as a raw dict
1099        :rtype: dict
1100        """
1101        pass
1102
1103    @abstractmethod
1104    def delete_device_config(self, account_key: str, name: str) -> None:
1105        """ Delete every version of a named Device Config. Requires the "custom-device-config"
1106        account feature. Idempotent.
1107
1108        :param str account_key: The unique key of the account
1109        :param str name: The name of the Device Config to delete
1110        """
1111        pass
1112
1113    @abstractmethod
1114    def start_device_config_development(self, account_key: str, name: str) -> dict:
1115        """ Branch a new development version off the current published one for an existing name.
1116        Requires the "custom-device-config" account feature. Fails if the name does not exist yet
1117        (use create), a development version is already in progress, or there is no published
1118        version to branch from.
1119
1120        :param str account_key: The unique key of the account
1121        :param str name: The name of the Device Config
1122        :return: The new development version, as a raw dict
1123        :rtype: dict
1124        """
1125        pass
1126
1127    @abstractmethod
1128    def discard_device_config_development(self, account_key: str, name: str) -> None:
1129        """ Delete the current development version outright, without publishing it. Requires the
1130        "custom-device-config" account feature. Idempotent - succeeds even if none is in progress.
1131
1132        :param str account_key: The unique key of the account
1133        :param str name: The name of the Device Config
1134        """
1135        pass
1136
1137    @abstractmethod
1138    def publish_device_config(self, account_key: str, name: str, semantic_version: str) -> dict:
1139        """ Flip the current development version's status to published in place. Requires the
1140        "custom-device-config" account feature. Fails if no development version is in progress,
1141        or if `semantic_version` is not strictly greater than this name's current published
1142        semantic version (if any).
1143
1144        :param str account_key: The unique key of the account
1145        :param str name: The name of the Device Config
1146        :param str semantic_version: The human-authored major.minor.patch version for this publish
1147        :return: The now-published version, as a raw dict
1148        :rtype: dict
1149        """
1150        pass
1151
1152    @abstractmethod
1153    def withdraw_device_config(self, account_key: str, name: str, version: int) -> dict:
1154        """ Hide one published Device Config version from consumer-facing fetch/sync/search/
1155        download without deleting it. Requires the "custom-device-config" account feature. Fails
1156        if that version isn't published.
1157
1158        :param str account_key: The unique key of the account
1159        :param str name: The name of the Device Config
1160        :param int version: The published version to withdraw
1161        :return: The now-withdrawn version, as a raw dict
1162        :rtype: dict
1163        """
1164        pass
1165
1166    @abstractmethod
1167    def republish_device_config(self, account_key: str, name: str, version: int) -> dict:
1168        """ Reverse a withdraw. Requires the "custom-device-config" account feature. Idempotent -
1169        succeeds even if the version wasn't withdrawn.
1170
1171        :param str account_key: The unique key of the account
1172        :param str name: The name of the Device Config
1173        :param int version: The withdrawn version to republish
1174        :return: The now-republished version, as a raw dict
1175        :rtype: dict
1176        """
1177        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def find_account(self, account_key: str) -> inmotion.models.AccountDetailsModel:
707    @abstractmethod
708    def find_account(self, account_key: str) -> AccountDetailsModel:
709        """ Find an account by its unique key
710
711        :param str account_key: The unique key of the account
712        :return: The account details
713        :rtype: AccountDetailsModel
714        """
715        pass

Find an account by its unique key

Parameters
  • str account_key: The unique key of the account
Returns

The account details

@abstractmethod
def find_account_tags(self, account_key: str) -> inmotion.models.AccountTagsModel:
717    @abstractmethod
718    def find_account_tags(self, account_key: str) -> AccountTagsModel:
719        """ Find the tags associated with an account
720
721        :param str account_key: The unique key of the account
722        :return: The account's tags
723        :rtype: AccountTagsModel
724        """
725        pass

Find the tags associated with an account

Parameters
  • str account_key: The unique key of the account
Returns

The account's tags

@abstractmethod
def update_account( self, account_key: str, account: inmotion.models.AccountModel) -> inmotion.models.AccountDetailsModel:
727    @abstractmethod
728    def update_account(self, account_key: str, account: AccountModel) -> AccountDetailsModel:
729        """ Update the details of an existing account
730
731        :param str account_key: The unique key of the account to update
732        :param AccountModel account: The updated account definition
733        :return: The updated account details
734        :rtype: AccountDetailsModel
735        """
736        pass

Update the details of an existing account

Parameters
  • str account_key: The unique key of the account to update
  • AccountModel account: The updated account definition
Returns

The updated account details

@abstractmethod
def find_account_users(self, account_key: str) -> list[inmotion.models.AccountUserSummaryModel]:
738    @abstractmethod
739    def find_account_users(self, account_key: str) -> list[AccountUserSummaryModel]:
740        """ Retrieve the users associated with an account
741
742        :param str account_key: The unique key of the account
743        :return: The users linked to the account
744        :rtype: list[AccountUserSummaryModel]
745        """
746        pass

Retrieve the users associated with an account

Parameters
  • str account_key: The unique key of the account
Returns

The users linked to the account

@abstractmethod
def register_account_user( self, account_key: str, user_key: str, privileges: inmotion.models.AccountPrivilegesModel) -> list[inmotion.models.AccountUserSummaryModel]:
748    @abstractmethod
749    def register_account_user(self, account_key: str, user_key: str, privileges: AccountPrivilegesModel) -> list[AccountUserSummaryModel]:
750        """ Register a user to an account
751
752        :param str account_key: The unique key of the account
753        :param str user_key: The unique key of the user to register
754        :param AccountPrivilegesModel privileges: The privileges to grant the user on the account
755        :return: The users linked to the account after registration
756        :rtype: list[AccountUserSummaryModel]
757        """
758        pass

Register a user to an account

Parameters
  • str account_key: The unique key of the account
  • str user_key: The unique key of the user to register
  • AccountPrivilegesModel privileges: The privileges to grant the user on the account
Returns

The users linked to the account after registration

@abstractmethod
def unregister_account_user( self, account_key: str, user_key: str) -> inmotion.models.AccountUserUnregisteredModel:
760    @abstractmethod
761    def unregister_account_user(self, account_key: str, user_key: str) -> AccountUserUnregisteredModel:
762        """ Unregister a user from an account
763
764        :param str account_key: The unique key of the account
765        :param str user_key: The unique key of the user to unregister
766        :return: The result of the unregister operation
767        :rtype: AccountUserUnregisteredModel
768        """
769        pass

Unregister a user from an account

Parameters
  • str account_key: The unique key of the account
  • str user_key: The unique key of the user to unregister
Returns

The result of the unregister operation

@abstractmethod
def batch_update_account_users( self, account_key: str, commands: list[inmotion.models.AccountUpdateBatchCommandModel]) -> inmotion.models.AccountUpdateBatchResultsModel:
771    @abstractmethod
772    def batch_update_account_users(self, account_key: str, commands: list[AccountUpdateBatchCommandModel]) -> AccountUpdateBatchResultsModel:
773        """ Apply a batch of register, unregister, or update actions to the users of an account
774
775        :param str account_key: The unique key of the account
776        :param list[AccountUpdateBatchCommandModel] commands: The batch of commands to apply
777        :return: The results of the batch update
778        :rtype: AccountUpdateBatchResultsModel
779        """
780        pass

Apply a batch of register, unregister, or update actions to the users of an account

Parameters
  • str account_key: The unique key of the account
  • list[AccountUpdateBatchCommandModel] commands: The batch of commands to apply
Returns

The results of the batch update

@abstractmethod
def create_account_only( self, account: inmotion.models.AccountModel) -> inmotion.models.AccountDetailsModel:
782    @abstractmethod
783    def create_account_only(self, account: AccountModel) -> AccountDetailsModel:
784        """ Create a new free personal account that is not yet associated with any user
785
786        :param AccountModel account: The definition of the account to create
787        :return: The created account's details
788        :rtype: AccountDetailsModel
789        """
790        pass

Create a new free personal account that is not yet associated with any user

Parameters
  • AccountModel account: The definition of the account to create
Returns

The created account's details

@abstractmethod
def request_account_data(self, account_key: str) -> inmotion.models.StatusMessageModel:
792    @abstractmethod
793    def request_account_data(self, account_key: str) -> StatusMessageModel:
794        """ Request a copy of all the account's data, which is prepared and sent to the owner.
795        Limited to a few requests per day.
796
797        :param str account_key: The unique key of the account (the caller must own it)
798        :return: The status of the request
799        :rtype: StatusMessageModel
800        """
801        pass

Request a copy of all the account's data, which is prepared and sent to the owner. Limited to a few requests per day.

Parameters
  • str account_key: The unique key of the account (the caller must own it)
Returns

The status of the request

@abstractmethod
def mark_account_for_deletion( self, account_key: str, and_user: bool) -> inmotion.models.AccountMarkedForDeletionModel:
803    @abstractmethod
804    def mark_account_for_deletion(self, account_key: str, and_user: bool) -> AccountMarkedForDeletionModel:
805        """ Mark an account for deletion
806
807        :param str account_key: The unique key of the account to mark for deletion
808        :param bool and_user: Whether the associated user should also be marked for deletion
809        :return: The result of the mark-for-deletion operation
810        :rtype: AccountMarkedForDeletionModel
811        """
812        pass

Mark an account for deletion

Parameters
  • str account_key: The unique key of the account to mark for deletion
  • bool and_user: Whether the associated user should also be marked for deletion
Returns

The result of the mark-for-deletion operation

@abstractmethod
def find_my_accounts(self) -> list[inmotion.models.UserAccountSummaryModel]:
814    @abstractmethod
815    def find_my_accounts(self) -> list[UserAccountSummaryModel]:
816        """ Fetch the accounts associated with the authenticated user
817
818        :return: The caller's summary of each account
819        :rtype: list[UserAccountSummaryModel]
820        """
821        pass

Fetch the accounts associated with the authenticated user

Returns

The caller's summary of each account

@abstractmethod
def fetch_global_device_configs(self) -> dict:
823    @abstractmethod
824    def fetch_global_device_configs(self) -> dict:
825        """ Fetch the system-wide default Device Configs (global tier), for runtime consumers to
826        merge with an account's own tier themselves - never merged here. Not account-scoped.
827
828        :return: A raw dict shaped `{ deviceConfigs: [{name, version, yaml}] }`
829        :rtype: dict
830        """
831        pass

Fetch the system-wide default Device Configs (global tier), for runtime consumers to merge with an account's own tier themselves - never merged here. Not account-scoped.

Returns

A raw dict shaped { deviceConfigs: [{name, version, yaml}] }

@abstractmethod
def sync_device_configs( self, request: inmotion.models.DeviceConfigSyncRequestModel) -> inmotion.models.DeviceConfigSyncResultModel:
833    @abstractmethod
834    def sync_device_configs(self, request: DeviceConfigSyncRequestModel) -> DeviceConfigSyncResultModel:
835        """ Fetch only the Device Config changes (global tier and a set of accounts) since a
836        given time, in one call
837
838        :param DeviceConfigSyncRequestModel request: The sync window and accounts to include
839        :return: The delta - entries changed since `since`, plus tombstones
840        :rtype: DeviceConfigSyncResultModel
841        """
842        pass

Fetch only the Device Config changes (global tier and a set of accounts) since a given time, in one call

Parameters
  • DeviceConfigSyncRequestModel request: The sync window and accounts to include
Returns

The delta - entries changed since since, plus tombstones

@abstractmethod
def add_account_member( self, account_key: str, request: inmotion.models.AddAccountMemberRequestModel) -> dict:
844    @abstractmethod
845    def add_account_member(self, account_key: str, request: AddAccountMemberRequestModel) -> dict:
846        """ Add someone to an account by username or email. If the value resolves to an existing inMotion
847        user they are registered immediately; otherwise (given `consent`) an external invite is sent instead.
848        Requires account admin.
849
850        :param str account_key: The unique key of the account
851        :param AddAccountMemberRequestModel request: Who to add, the access to grant, and the consent/message
852            used only if an invite has to be sent
853        :return: A dict discriminated by `kind` - `"member"` (with `user`, an account user summary) or
854            `"invite"` (with `invite`, a friend-invite)
855        :rtype: dict
856        """
857        pass

Add someone to an account by username or email. If the value resolves to an existing inMotion user they are registered immediately; otherwise (given consent) an external invite is sent instead. Requires account admin.

Parameters
  • str account_key: The unique key of the account
  • AddAccountMemberRequestModel request: Who to add, the access to grant, and the consent/message used only if an invite has to be sent
Returns

A dict discriminated by kind - "member" (with user, an account user summary) or "invite" (with invite, a friend-invite)

@abstractmethod
def send_friend_invite( self, account_key: str, request: inmotion.models.FriendInviteRequestModel) -> inmotion.models.FriendInviteModel:
859    @abstractmethod
860    def send_friend_invite(self, account_key: str, request: FriendInviteRequestModel) -> FriendInviteModel:
861        """ Invite someone who is not yet an inMotion user to join an account, by email. Rejected if the
862        email already belongs to a registered user. Requires account admin; rate limited per address.
863
864        :param str account_key: The unique key of the account
865        :param FriendInviteRequestModel request: The email to invite, `consent` (must be true) and an
866            optional personal note (max 200 characters)
867        :return: The created invite
868        :rtype: FriendInviteModel
869        """
870        pass

Invite someone who is not yet an inMotion user to join an account, by email. Rejected if the email already belongs to a registered user. Requires account admin; rate limited per address.

Parameters
  • str account_key: The unique key of the account
  • FriendInviteRequestModel request: The email to invite, consent (must be true) and an optional personal note (max 200 characters)
Returns

The created invite

@abstractmethod
def list_friend_invites(self, account_key: str) -> list[inmotion.models.FriendInviteModel]:
872    @abstractmethod
873    def list_friend_invites(self, account_key: str) -> list[FriendInviteModel]:
874        """ List the friend-invites sent from an account. Requires account admin.
875
876        :param str account_key: The unique key of the account
877        :return: The account's invites, whatever their status
878        :rtype: list[FriendInviteModel]
879        """
880        pass

List the friend-invites sent from an account. Requires account admin.

Parameters
  • str account_key: The unique key of the account
Returns

The account's invites, whatever their status

@abstractmethod
def revoke_friend_invite(self, account_key: str, token: str) -> inmotion.models.FriendInviteModel:
882    @abstractmethod
883    def revoke_friend_invite(self, account_key: str, token: str) -> FriendInviteModel:
884        """ Cancel a still-pending friend-invite so it can no longer be accepted. No-op if it was already
885        accepted or revoked. Requires account admin.
886
887        :param str account_key: The unique key of the account
888        :param str token: The invite's token
889        :return: The invite, as it now stands
890        :rtype: FriendInviteModel
891        """
892        pass

Cancel a still-pending friend-invite so it can no longer be accepted. No-op if it was already accepted or revoked. Requires account admin.

Parameters
  • str account_key: The unique key of the account
  • str token: The invite's token
Returns

The invite, as it now stands

@abstractmethod
def list_activity_types(self, account_key: str) -> list[dict]:
894    @abstractmethod
895    def list_activity_types(self, account_key: str) -> list[dict]:
896        """ List every Activity Type (global and account-scoped custom, each tagged its own `source`)
897        browsable by an account.
898
899        :param str account_key: The unique key of the account
900        :return: Every Activity Type entry, as raw dicts (no fixed schema is declared server-side)
901        :rtype: list[dict]
902        """
903        pass

List every Activity Type (global and account-scoped custom, each tagged its own source) browsable by an account.

Parameters
  • str account_key: The unique key of the account
Returns

Every Activity Type entry, as raw dicts (no fixed schema is declared server-side)

@abstractmethod
def find_account_activity_master_data(self, account_key: str) -> dict:
905    @abstractmethod
906    def find_account_activity_master_data(self, account_key: str) -> dict:
907        """ Fetch master data (profile types, standard data types and activity types) for an account.
908        Same shape as `InMotionActivities.find_activity_master_data`, but the activity types are the
909        account's merged set - the global catalog plus its own custom Activity Types, the account's
910        winning on a key collision. Readable by any account member.
911
912        :param str account_key: The unique key of the account
913        :return: The account's merged master data, as a raw dict
914        :rtype: dict
915        """
916        pass

Fetch master data (profile types, standard data types and activity types) for an account. Same shape as InMotionActivities.find_activity_master_data, but the activity types are the account's merged set - the global catalog plus its own custom Activity Types, the account's winning on a key collision. Readable by any account member.

Parameters
  • str account_key: The unique key of the account
Returns

The account's merged master data, as a raw dict

@abstractmethod
def create_activity_type(self, account_key: str, yaml_document: str) -> dict:
918    @abstractmethod
919    def create_activity_type(self, account_key: str, yaml_document: str) -> dict:
920        """ Create an account-scoped custom Activity Type. Requires the "custom-activity-type" account
921        feature. Fails if the account already has a custom Activity Type at that key.
922
923        :param str account_key: The unique key of the account
924        :param str yaml_document: A standalone single-entry YAML document; its identity is its own `key` field
925        :return: The created Activity Type entry, as a raw dict
926        :rtype: dict
927        """
928        pass

Create an account-scoped custom Activity Type. Requires the "custom-activity-type" account feature. Fails if the account already has a custom Activity Type at that key.

Parameters
  • str account_key: The unique key of the account
  • str yaml_document: A standalone single-entry YAML document; its identity is its own key field
Returns

The created Activity Type entry, as a raw dict

@abstractmethod
def update_activity_type(self, account_key: str, key: str, yaml_document: str) -> dict:
930    @abstractmethod
931    def update_activity_type(self, account_key: str, key: str, yaml_document: str) -> dict:
932        """ Update an account-scoped custom Activity Type. Requires the "custom-activity-type" account
933        feature. Fails if none exists yet at `key` (use create_activity_type), or if the document's own
934        `key` field doesn't match `key`.
935
936        :param str account_key: The unique key of the account
937        :param str key: The key of the custom Activity Type to update
938        :param str yaml_document: A standalone single-entry YAML document
939        :return: The updated Activity Type entry, as a raw dict
940        :rtype: dict
941        """
942        pass

Update an account-scoped custom Activity Type. Requires the "custom-activity-type" account feature. Fails if none exists yet at key (use create_activity_type), or if the document's own key field doesn't match key.

Parameters
  • str account_key: The unique key of the account
  • str key: The key of the custom Activity Type to update
  • str yaml_document: A standalone single-entry YAML document
Returns

The updated Activity Type entry, as a raw dict

@abstractmethod
def delete_activity_type(self, account_key: str, key: str) -> None:
944    @abstractmethod
945    def delete_activity_type(self, account_key: str, key: str) -> None:
946        """ Delete an account-scoped custom Activity Type. Idempotent. Requires the "custom-activity-type"
947        account feature.
948
949        :param str account_key: The unique key of the account
950        :param str key: The key of the custom Activity Type to delete
951        """
952        pass

Delete an account-scoped custom Activity Type. Idempotent. Requires the "custom-activity-type" account feature.

Parameters
  • str account_key: The unique key of the account
  • str key: The key of the custom Activity Type to delete
@abstractmethod
def list_standard_data_types(self, account_key: str) -> list[dict]:
954    @abstractmethod
955    def list_standard_data_types(self, account_key: str) -> list[dict]:
956        """ List every Standard Data Type entry (global and account, each tagged its own
957        `source`) visible to an account. Requires the "custom-sdt" account feature.
958
959        :param str account_key: The unique key of the account
960        :return: Every Standard Data Type entry, as raw dicts (no fixed schema is declared server-side)
961        :rtype: list[dict]
962        """
963        pass

List every Standard Data Type entry (global and account, each tagged its own source) visible to an account. Requires the "custom-sdt" account feature.

Parameters
  • str account_key: The unique key of the account
Returns

Every Standard Data Type entry, as raw dicts (no fixed schema is declared server-side)

@abstractmethod
def create_standard_data_type(self, account_key: str, yaml_document: str) -> dict:
965    @abstractmethod
966    def create_standard_data_type(self, account_key: str, yaml_document: str) -> dict:
967        """ Create an account-scoped Standard Data Type override. Requires the "custom-sdt"
968        account feature. Fails if the account already has an override at the document's own
969        `key`, or the document references an unknown `variant-type`.
970
971        :param str account_key: The unique key of the account
972        :param str yaml_document: A standalone single-entry YAML document; its identity is its own `key` field
973        :return: The created Standard Data Type entry, as a raw dict
974        :rtype: dict
975        """
976        pass

Create an account-scoped Standard Data Type override. Requires the "custom-sdt" account feature. Fails if the account already has an override at the document's own key, or the document references an unknown variant-type.

Parameters
  • str account_key: The unique key of the account
  • str yaml_document: A standalone single-entry YAML document; its identity is its own key field
Returns

The created Standard Data Type entry, as a raw dict

@abstractmethod
def update_standard_data_type(self, account_key: str, key: str, yaml_document: str) -> dict:
978    @abstractmethod
979    def update_standard_data_type(self, account_key: str, key: str, yaml_document: str) -> dict:
980        """ Update an account-scoped Standard Data Type override. Fails if no override exists yet
981        at `key` (use create instead), or if the document's own `key` field doesn't match.
982        Requires the "custom-sdt" account feature.
983
984        :param str account_key: The unique key of the account
985        :param str key: The key of the Standard Data Type override to update
986        :param str yaml_document: The replacement standalone single-entry YAML document
987        :return: The updated Standard Data Type entry, as a raw dict
988        :rtype: dict
989        """
990        pass

Update an account-scoped Standard Data Type override. Fails if no override exists yet at key (use create instead), or if the document's own key field doesn't match. Requires the "custom-sdt" account feature.

Parameters
  • str account_key: The unique key of the account
  • str key: The key of the Standard Data Type override to update
  • str yaml_document: The replacement standalone single-entry YAML document
Returns

The updated Standard Data Type entry, as a raw dict

@abstractmethod
def delete_standard_data_type(self, account_key: str, key: str) -> None:
 992    @abstractmethod
 993    def delete_standard_data_type(self, account_key: str, key: str) -> None:
 994        """ Delete an account-scoped Standard Data Type override. Idempotent. Requires the
 995        "custom-sdt" account feature.
 996
 997        :param str account_key: The unique key of the account
 998        :param str key: The key of the Standard Data Type override to delete
 999        """
1000        pass

Delete an account-scoped Standard Data Type override. Idempotent. Requires the "custom-sdt" account feature.

Parameters
  • str account_key: The unique key of the account
  • str key: The key of the Standard Data Type override to delete
@abstractmethod
def list_standard_data_variant_types(self, account_key: str) -> list[dict]:
1002    @abstractmethod
1003    def list_standard_data_variant_types(self, account_key: str) -> list[dict]:
1004        """ List every Standard Data Variant Type entry (global and account, each tagged its own
1005        `source`) visible to an account. Requires the "custom-sdt" account feature.
1006
1007        :param str account_key: The unique key of the account
1008        :return: Every Standard Data Variant Type entry, as raw dicts
1009        :rtype: list[dict]
1010        """
1011        pass

List every Standard Data Variant Type entry (global and account, each tagged its own source) visible to an account. Requires the "custom-sdt" account feature.

Parameters
  • str account_key: The unique key of the account
Returns

Every Standard Data Variant Type entry, as raw dicts

@abstractmethod
def create_standard_data_variant_type(self, account_key: str, yaml_document: str) -> dict:
1013    @abstractmethod
1014    def create_standard_data_variant_type(self, account_key: str, yaml_document: str) -> dict:
1015        """ Create an account-scoped Standard Data Variant Type override. Requires the
1016        "custom-sdt" account feature. Fails if the account already has an override at the
1017        document's own `key`.
1018
1019        :param str account_key: The unique key of the account
1020        :param str yaml_document: A standalone single-entry YAML document; its identity is its own `key` field
1021        :return: The created Standard Data Variant Type entry, as a raw dict
1022        :rtype: dict
1023        """
1024        pass

Create an account-scoped Standard Data Variant Type override. Requires the "custom-sdt" account feature. Fails if the account already has an override at the document's own key.

Parameters
  • str account_key: The unique key of the account
  • str yaml_document: A standalone single-entry YAML document; its identity is its own key field
Returns

The created Standard Data Variant Type entry, as a raw dict

@abstractmethod
def update_standard_data_variant_type(self, account_key: str, key: str, yaml_document: str) -> dict:
1026    @abstractmethod
1027    def update_standard_data_variant_type(self, account_key: str, key: str, yaml_document: str) -> dict:
1028        """ Update an account-scoped Standard Data Variant Type override. Fails if no override
1029        exists yet at `key`, or if the document's own `key` field doesn't match. Requires the
1030        "custom-sdt" account feature.
1031
1032        :param str account_key: The unique key of the account
1033        :param str key: The key of the Standard Data Variant Type override to update
1034        :param str yaml_document: The replacement standalone single-entry YAML document
1035        :return: The updated Standard Data Variant Type entry, as a raw dict
1036        :rtype: dict
1037        """
1038        pass

Update an account-scoped Standard Data Variant Type override. Fails if no override exists yet at key, or if the document's own key field doesn't match. Requires the "custom-sdt" account feature.

Parameters
  • str account_key: The unique key of the account
  • str key: The key of the Standard Data Variant Type override to update
  • str yaml_document: The replacement standalone single-entry YAML document
Returns

The updated Standard Data Variant Type entry, as a raw dict

@abstractmethod
def delete_standard_data_variant_type(self, account_key: str, key: str) -> None:
1040    @abstractmethod
1041    def delete_standard_data_variant_type(self, account_key: str, key: str) -> None:
1042        """ Delete an account-scoped Standard Data Variant Type override. Fails, naming the
1043        referencing Data Type keys, if any of the account's own Data Types currently reference
1044        this variant type. Idempotent otherwise. Requires the "custom-sdt" account feature.
1045
1046        :param str account_key: The unique key of the account
1047        :param str key: The key of the Standard Data Variant Type override to delete
1048        """
1049        pass

Delete an account-scoped Standard Data Variant Type override. Fails, naming the referencing Data Type keys, if any of the account's own Data Types currently reference this variant type. Idempotent otherwise. Requires the "custom-sdt" account feature.

Parameters
  • str account_key: The unique key of the account
  • str key: The key of the Standard Data Variant Type override to delete
@abstractmethod
def fetch_device_configs(self, account_key: str, preview: bool = False) -> dict:
1051    @abstractmethod
1052    def fetch_device_configs(self, account_key: str, preview: bool = False) -> dict:
1053        """ Fetch an account's own tier of Device Configs, for runtime consumers to merge with
1054        the global tier themselves - never merged here. Always succeeds with an empty list if
1055        nothing has been published yet.
1056
1057        :param str account_key: The unique key of the account
1058        :param bool preview: If True, serves the in-progress development version per name where
1059            one exists (falling back to published) - restricted to the account's admins/owners
1060        :return: A raw dict shaped `{ deviceConfigs: [{name, version, yaml}] }`
1061        :rtype: dict
1062        """
1063        pass

Fetch an account's own tier of Device Configs, for runtime consumers to merge with the global tier themselves - never merged here. Always succeeds with an empty list if nothing has been published yet.

Parameters
  • str account_key: The unique key of the account
  • bool preview: If True, serves the in-progress development version per name where one exists (falling back to published) - restricted to the account's admins/owners
Returns

A raw dict shaped { deviceConfigs: [{name, version, yaml}] }

@abstractmethod
def list_device_configs(self, account_key: str) -> dict:
1065    @abstractmethod
1066    def list_device_configs(self, account_key: str) -> dict:
1067        """ List every version of every one of the account's named Device Configs, for an
1068        editing UI. Requires the "custom-device-config" account feature.
1069
1070        :param str account_key: The unique key of the account
1071        :return: A raw dict shaped `{ deviceConfigs: [...] }`
1072        :rtype: dict
1073        """
1074        pass

List every version of every one of the account's named Device Configs, for an editing UI. Requires the "custom-device-config" account feature.

Parameters
  • str account_key: The unique key of the account
Returns

A raw dict shaped { deviceConfigs: [...] }

@abstractmethod
def create_device_config(self, account_key: str, yaml_document: str) -> dict:
1076    @abstractmethod
1077    def create_device_config(self, account_key: str, yaml_document: str) -> dict:
1078        """ Validate and create a brand-new Device Config at version 1, status development.
1079        Requires the "custom-device-config" account feature. Fails if a Device Config with that
1080        name already exists for this account.
1081
1082        :param str account_key: The unique key of the account
1083        :param str yaml_document: The Device Config document; its identity is its own `profile.name` field
1084        :return: The new Device Config's id/version/status/yaml/updatedAt/updatedBy, as a raw dict
1085        :rtype: dict
1086        """
1087        pass

Validate and create a brand-new Device Config at version 1, status development. Requires the "custom-device-config" account feature. Fails if a Device Config with that name already exists for this account.

Parameters
  • str account_key: The unique key of the account
  • str yaml_document: The Device Config document; its identity is its own profile.name field
Returns

The new Device Config's id/version/status/yaml/updatedAt/updatedBy, as a raw dict

@abstractmethod
def save_device_config(self, account_key: str, name: str, yaml_document: str) -> dict:
1089    @abstractmethod
1090    def save_device_config(self, account_key: str, name: str, yaml_document: str) -> dict:
1091        """ Validate and save new content to the current development version of a named Device
1092        Config, in place. Requires the "custom-device-config" account feature. Fails if no
1093        development version is in progress.
1094
1095        :param str account_key: The unique key of the account
1096        :param str name: The name of the Device Config
1097        :param str yaml_document: The replacement Device Config document
1098        :return: The updated Device Config version, as a raw dict
1099        :rtype: dict
1100        """
1101        pass

Validate and save new content to the current development version of a named Device Config, in place. Requires the "custom-device-config" account feature. Fails if no development version is in progress.

Parameters
  • str account_key: The unique key of the account
  • str name: The name of the Device Config
  • str yaml_document: The replacement Device Config document
Returns

The updated Device Config version, as a raw dict

@abstractmethod
def delete_device_config(self, account_key: str, name: str) -> None:
1103    @abstractmethod
1104    def delete_device_config(self, account_key: str, name: str) -> None:
1105        """ Delete every version of a named Device Config. Requires the "custom-device-config"
1106        account feature. Idempotent.
1107
1108        :param str account_key: The unique key of the account
1109        :param str name: The name of the Device Config to delete
1110        """
1111        pass

Delete every version of a named Device Config. Requires the "custom-device-config" account feature. Idempotent.

Parameters
  • str account_key: The unique key of the account
  • str name: The name of the Device Config to delete
@abstractmethod
def start_device_config_development(self, account_key: str, name: str) -> dict:
1113    @abstractmethod
1114    def start_device_config_development(self, account_key: str, name: str) -> dict:
1115        """ Branch a new development version off the current published one for an existing name.
1116        Requires the "custom-device-config" account feature. Fails if the name does not exist yet
1117        (use create), a development version is already in progress, or there is no published
1118        version to branch from.
1119
1120        :param str account_key: The unique key of the account
1121        :param str name: The name of the Device Config
1122        :return: The new development version, as a raw dict
1123        :rtype: dict
1124        """
1125        pass

Branch a new development version off the current published one for an existing name. Requires the "custom-device-config" account feature. Fails if the name does not exist yet (use create), a development version is already in progress, or there is no published version to branch from.

Parameters
  • str account_key: The unique key of the account
  • str name: The name of the Device Config
Returns

The new development version, as a raw dict

@abstractmethod
def discard_device_config_development(self, account_key: str, name: str) -> None:
1127    @abstractmethod
1128    def discard_device_config_development(self, account_key: str, name: str) -> None:
1129        """ Delete the current development version outright, without publishing it. Requires the
1130        "custom-device-config" account feature. Idempotent - succeeds even if none is in progress.
1131
1132        :param str account_key: The unique key of the account
1133        :param str name: The name of the Device Config
1134        """
1135        pass

Delete the current development version outright, without publishing it. Requires the "custom-device-config" account feature. Idempotent - succeeds even if none is in progress.

Parameters
  • str account_key: The unique key of the account
  • str name: The name of the Device Config
@abstractmethod
def publish_device_config(self, account_key: str, name: str, semantic_version: str) -> dict:
1137    @abstractmethod
1138    def publish_device_config(self, account_key: str, name: str, semantic_version: str) -> dict:
1139        """ Flip the current development version's status to published in place. Requires the
1140        "custom-device-config" account feature. Fails if no development version is in progress,
1141        or if `semantic_version` is not strictly greater than this name's current published
1142        semantic version (if any).
1143
1144        :param str account_key: The unique key of the account
1145        :param str name: The name of the Device Config
1146        :param str semantic_version: The human-authored major.minor.patch version for this publish
1147        :return: The now-published version, as a raw dict
1148        :rtype: dict
1149        """
1150        pass

Flip the current development version's status to published in place. Requires the "custom-device-config" account feature. Fails if no development version is in progress, or if semantic_version is not strictly greater than this name's current published semantic version (if any).

Parameters
  • str account_key: The unique key of the account
  • str name: The name of the Device Config
  • str semantic_version: The human-authored major.minor.patch version for this publish
Returns

The now-published version, as a raw dict

@abstractmethod
def withdraw_device_config(self, account_key: str, name: str, version: int) -> dict:
1152    @abstractmethod
1153    def withdraw_device_config(self, account_key: str, name: str, version: int) -> dict:
1154        """ Hide one published Device Config version from consumer-facing fetch/sync/search/
1155        download without deleting it. Requires the "custom-device-config" account feature. Fails
1156        if that version isn't published.
1157
1158        :param str account_key: The unique key of the account
1159        :param str name: The name of the Device Config
1160        :param int version: The published version to withdraw
1161        :return: The now-withdrawn version, as a raw dict
1162        :rtype: dict
1163        """
1164        pass

Hide one published Device Config version from consumer-facing fetch/sync/search/ download without deleting it. Requires the "custom-device-config" account feature. Fails if that version isn't published.

Parameters
  • str account_key: The unique key of the account
  • str name: The name of the Device Config
  • int version: The published version to withdraw
Returns

The now-withdrawn version, as a raw dict

@abstractmethod
def republish_device_config(self, account_key: str, name: str, version: int) -> dict:
1166    @abstractmethod
1167    def republish_device_config(self, account_key: str, name: str, version: int) -> dict:
1168        """ Reverse a withdraw. Requires the "custom-device-config" account feature. Idempotent -
1169        succeeds even if the version wasn't withdrawn.
1170
1171        :param str account_key: The unique key of the account
1172        :param str name: The name of the Device Config
1173        :param int version: The withdrawn version to republish
1174        :return: The now-republished version, as a raw dict
1175        :rtype: dict
1176        """
1177        pass

Reverse a withdraw. Requires the "custom-device-config" account feature. Idempotent - succeeds even if the version wasn't withdrawn.

Parameters
  • str account_key: The unique key of the account
  • str name: The name of the Device Config
  • int version: The withdrawn version to republish
Returns

The now-republished version, as a raw dict

class InMotionActivities(abc.ABC):
141class InMotionActivities(ABC):
142    @abstractmethod
143    def find_activities(self, act_filter: ActivitySearchFilterModel) -> ActivitiesModel:
144        """
145        Retrieve all site based activities that contain observational data
146
147        :param ActivitySearchFilterModel act_filter: The filter to apply to the search
148        :return: The activities that match the filter
149        :rtype: ActivitiesModel
150        """
151        pass
152
153    @abstractmethod
154    def find_activities_within_time_range(self, act_filter: ActivitySearchFilterModel, start: datetime, finish: datetime) -> ActivitiesModel:
155        """
156        Retrieve all site based activities that contain observational data within the specified time range.
157
158        :param ActivitySearchFilterModel act_filter: The filter to apply to the search
159        :param datetime start: The start of the time range (inclusive)
160        :param datetime finish: The end of the time range (inclusive)
161        :return: The activities that match the filter and time range
162        :rtype: ActivitiesModel
163        """
164        pass
165
166    @abstractmethod
167    def find_latest_activity_stats(self, since: datetime, lite: bool = False) -> LastActivitiesModel:
168        """ Retrieve the latest records for all activities since the provided date
169
170        :param datetime since: The date/time to search from
171        :param bool lite: If true, each sensor carries only its last value, without the statistics over the window
172        :return: The latest activities since the specified date
173        :rtype: LastActivitiesModel
174        """
175        pass
176
177    @abstractmethod
178    def find_latest_activity_stats_by_type(self, since: datetime, coord_conv: str, lite: bool = False) -> LastActivitiesModel:
179        """ Retrieve the latest records for all activities of a specific Coordinate Convention since the provided date
180
181        :param datetime since: The date/time to search from
182        :param str coord_conv: The Coordinate Convention to restrict results to (see CoordinateConvention)
183        :param bool lite: If true, each sensor carries only its last value, without the statistics over the window
184        :return: The latest activities since the specified date
185        :rtype: LastActivitiesModel
186        """
187        pass
188
189    @abstractmethod
190    def find_activity_master_data(self) -> MasterDataModel:
191        """ Fetch master data related to activities (profile types and activity types)
192
193        :return: The activity master data
194        :rtype: MasterDataModel
195        """
196        pass
197
198    @abstractmethod
199    def find_activity_analytics(self, request: ActivityAnalyticsRequestModel) -> ActivityAnalyticsResultModel:
200        """ Retrieve grouped activity counts across one or more accounts (or, if none are
201        supplied, every account the caller can access)
202
203        :param ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
204        :return: The grouped activity counts
205        :rtype: ActivityAnalyticsResultModel
206        """
207        pass
208
209    @abstractmethod
210    def find_activity_track_metrics(self, request: ActivityAnalyticsRequestModel) -> ActivityTrackMetricsResultModel:
211        """ Retrieve aggregate track metrics (distance/ascent/descent/duration/speed) across one
212        or more accounts, for TRACK-kind activities only
213
214        :param ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
215        :return: The grouped track metrics
216        :rtype: ActivityTrackMetricsResultModel
217        """
218        pass
219
220    @abstractmethod
221    def find_activity_variable_stats(self, request: ActivityAnalyticsRequestModel) -> ActivityVariableStatsResultModel:
222        """ Retrieve aggregate, per-standard-data-type variable statistics across one or more
223        accounts, for TRACK-kind activities only
224
225        :param ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
226        :return: The grouped variable statistics
227        :rtype: ActivityVariableStatsResultModel
228        """
229        pass
230
231    @abstractmethod
232    def batch_record_update(self, commands: ActivityBatchCommandsModel) -> list[ActivityBatchResultModel]:
233        """ Apply a batch of track and/or site activity create/update commands in a single request
234
235        :param ActivityBatchCommandsModel commands: The batch of track and/or site commands to apply
236        :return: The per-command results, matched back to their command via `seqKey`
237        :rtype: list[ActivityBatchResultModel]
238        """
239        pass
240
241    @abstractmethod
242    def create_track_activity(self, activity: CreateTrackActivityModel) -> ActivityUpdateResponseModel:
243        """ Create a track activity based on the definition
244
245        :param CreateTrackActivityModel activity: The definition of the track activity to create
246        :return: The response from the creation of the activity
247        :rtype: ActivityUpdateResponseModel
248        """
249        pass
250
251    @abstractmethod
252    def update_track_activity(self, track_key: str, activity: UpdateTrackActivityModel) -> ActivityUpdateResponseModel:
253        """ Update a track activity based on the definition
254
255        :param str track_key: The unique key of the track activity to update
256        :param UpdateTrackActivityModel activity: The updated definition of the track activity
257        :return: The response from the update of the activity
258        """
259        pass
260
261    @abstractmethod
262    def find_track_activity(self, track_key: str) -> TrackActivityModel:
263        """ Retrieve the details for the requested inMotion track
264
265        :param str track_key: The unique key of the track activity to retrieve
266        :return: The details of the track activity
267        :rtype: TrackActivityDetails
268        """
269        pass
270
271    @abstractmethod
272    def delete_track_activity(self, track_key: str) -> None:
273        """ Delete a track activity and all of its associated records
274
275        :param str track_key: The unique key of the track activity to delete
276        """
277        pass
278
279    @abstractmethod
280    def finish_track_activity(self, track_key: str) -> None:
281        """ Make a track that was created with ``uploadState="uploading"`` visible, once all its records are sent
282
283        :param str track_key: The unique key of the track activity to finish
284        """
285        pass
286
287    @abstractmethod
288    def unlock_track_activity(self, track_key: str) -> None:
289        """ Unlock a track activity so that it can be modified or updated
290
291        :param str track_key: The unique key of the track activity to unlock
292        """
293        pass
294
295    @abstractmethod
296    def get_track_records(self, track_key: str, start_time: Optional[datetime], end_time: Optional[datetime]) -> TrackRecordsModel:
297        """ Retrieve records from inMotion within the requested time-period
298
299        :param str track_key: The unique key of the track activity to retrieve records from
300        :param Optional[datetime] start_time: The start of the time range (inclusive)
301        :param Optional[datetime] end_time: The end of the time range (inclusive)
302        :return: The records for the track activity within the specified time range
303        :rtype: TrackRecords
304        """
305        pass
306
307    @abstractmethod
308    def find_all_track_records(self, track_key: str, after: Optional[datetime] = None) -> TrackRecordsModel:
309        """ Retrieve the records for a track activity, without an upper time restriction
310
311        :param str track_key: The unique key of the track activity to retrieve records from
312        :param Optional[datetime] after: If given, only records recorded after this time are returned. The
313            statistics and markers are still those of the whole track, and `lastRecorded` on the result
314            gives the time of the track's final record - pass it back as `after` to poll for new records.
315        :return: The records for the track activity
316        :rtype: TrackRecordsModel
317        """
318        pass
319
320    @abstractmethod
321    def publish_track_records(self, track_key: str, records: dict[str, list[int | float]]) -> ActivityUpdateResponseModel:
322        """ Publish a set of track records to inmotion
323
324        :param str track_key: The unique key of the track activity to publish records to
325        :param dict[str, list[int | float]] records: The records to publish, where the key is the field name and the value is a list of values
326        :return: The response from the publish of the records
327        :rtype: ActivityUpdateResponseModel
328        """
329        pass
330
331    @abstractmethod
332    def download_track_records(self, track_key: str, file_format: str) -> bytes:
333        """ Download the records of a track activity in the requested format
334
335        :param str track_key: The unique key of the track activity to download records from
336        :param str file_format: The format to download the records in ('csv', 'json' or 'gpx')
337        :return: The raw file content
338        :rtype: bytes
339        """
340        pass
341
342    @abstractmethod
343    def share_track_activity(self, track_key: str, kind: str) -> None:
344        """ Share a track activity
345
346        :param str track_key: The unique key of the track activity to share
347        :param str kind: The kind of sharing to apply ('any' or 'private')
348        """
349        pass
350
351    @abstractmethod
352    def unshare_track_activity(self, track_key: str, kind: str) -> None:
353        """ Remove sharing from a track activity
354
355        :param str track_key: The unique key of the track activity to unshare
356        :param str kind: The kind of sharing to revoke
357        """
358        pass
359
360    @abstractmethod
361    def find_shared_track_activity(self, track_key: str) -> TrackActivityModel:
362        """ Retrieve the details of a shared track activity
363
364        :param str track_key: The unique key of the shared track activity to retrieve
365        :return: The details of the shared track activity
366        :rtype: TrackActivityModel
367        """
368        pass
369
370    @abstractmethod
371    def find_all_shared_track_records(self, track_key: str) -> TrackRecordsModel:
372        """ Retrieve all records of a shared track activity
373
374        :param str track_key: The unique key of the shared track activity to retrieve records from
375        :return: All records for the shared track activity
376        :rtype: TrackRecordsModel
377        """
378        pass
379
380    @abstractmethod
381    def convert_track_to_route(self, track_key: str, name: Optional[str] = None) -> str:
382        """ Create a new, standalone Coverage/Route Shape from a track activity's GPS records.
383        The original track is left untouched - this is a derived record, not an in-place nature
384        change. Gated by the "track-to-shape" account feature.
385
386        :param str track_key: The unique key of the track activity to convert
387        :param Optional[str] name: An optional name for the new Route shape. Defaults to
388            "<track name> (Route)" when omitted.
389        :return: The new shape's key
390        :rtype: str
391        """
392        pass
393
394    @abstractmethod
395    def preview_track_records(self, track_key: str, qc_config: QCConfigModel) -> dict:
396        """ Retrieve records for a track activity with an ephemeral QC configuration applied. The
397        config is not saved.
398
399        :param str track_key: The unique key of the track activity to preview records for
400        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
401        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
402        :rtype: dict
403        """
404        pass
405
406    @abstractmethod
407    def preview_track_records_within_range(self, track_key: str, start_time: datetime, end_time: datetime, qc_config: QCConfigModel) -> dict:
408        """ Retrieve records for a track activity within a time range with an ephemeral QC
409        configuration applied. The config is not saved.
410
411        :param str track_key: The unique key of the track activity to preview records for
412        :param datetime start_time: The start of the time range (inclusive)
413        :param datetime end_time: The end of the time range (inclusive)
414        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
415        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
416        :rtype: dict
417        """
418        pass
419
420    @abstractmethod
421    def find_track_model_field_groups(self, track_key: str) -> list[ModelFieldGroupModel]:
422        """ Find a track activity's custom classification field values - one field group per
423        active classification tag on this track.
424
425        :param str track_key: The unique key of the track activity
426        :return: The track activity's active classification field groups
427        :rtype: list[ModelFieldGroupModel]
428        """
429        pass
430
431    @abstractmethod
432    def set_track_model_field_value(self, track_key: str, request: SetModelFieldValueRequestModel) -> list[ModelFieldGroupModel]:
433        """ Set (or, if value is omitted/blank on an optional field, clear) one custom
434        classification field's value for one active tag on a track activity.
435
436        :param str track_key: The unique key of the track activity
437        :param SetModelFieldValueRequestModel request: The field value to set
438        :return: The track activity's active classification field groups, including the updated value
439        :rtype: list[ModelFieldGroupModel]
440        """
441        pass
442
443    @abstractmethod
444    def create_site_activity(self, activity: CreateSiteActivityModel) -> ActivityUpdateResponseModel:
445        """ Create a site activity based on the definition
446
447        :param CreateSiteActivityModel activity: The definition of the site activity to create
448        :return: The response from the creation of the activity
449        :rtype: ActivityUpdateResponseModel
450        """
451        pass
452
453    @abstractmethod
454    def update_site_activity(self, site_key: str, activity: UpdateSiteActivityModel) -> ActivityUpdateResponseModel:
455        """ Update a site activity based on the definition
456
457        :param str site_key: The unique key of the site activity to update
458        :param UpdateSiteActivityModel activity: The updated definition of the site activity
459        :return: The response from the update of the activity
460        :rtype: ActivityUpdateResponseModel
461        """
462        pass
463
464    @abstractmethod
465    def find_site_activity(self, site_key: str) -> SiteActivityModel:
466        """ Retrieve the details for the requested inMotion site
467
468        :param str site_key: The unique key of the site activity to retrieve
469        :return: The details of the site activity
470        :rtype: SiteActivityModel
471
472        """
473        pass
474
475    @abstractmethod
476    def delete_site_activity(self, site_key: str) -> None:
477        """ Delete a site activity and all of its associated records
478
479        :param str site_key: The unique key of the site activity to delete
480        """
481        pass
482
483    @abstractmethod
484    def unlock_site_activity(self, site_key: str) -> None:
485        """ Unlock a site activity so that it can be modified or updated
486
487        :param str site_key: The unique key of the site activity to unlock
488        """
489        pass
490
491    @abstractmethod
492    def get_site_records(self, site_key: str, start_time: Optional[datetime], end_time: Optional[datetime]) -> SiteRecordsModel:
493        """ Retrieve records from inMotion within the requested time-period
494
495        :param str site_key: The unique key of the site activity to retrieve records from
496        :param Optional[datetime] start_time: The start of the time range (inclusive)
497        :param Optional[datetime] end_time: The end of the time range (inclusive)
498        :return: The records for the site activity within the specified time range
499        :rtype: SiteRecords
500        """
501        pass
502
503    @abstractmethod
504    def find_all_site_records(self, site_key: str, after: Optional[datetime] = None) -> SiteRecordsModel:
505        """ Retrieve all records for a site activity, without a time range restriction
506
507        :param str site_key: The unique key of the site activity to retrieve records from
508        :param Optional[datetime] after: If given, only records recorded after this time are returned. The
509            statistics are still those of all the records, and `lastRecorded` on the result gives the time
510            of the final record - pass it back as `after` to poll for new records.
511        :return: All records for the site activity
512        :rtype: SiteRecordsModel
513        """
514        pass
515
516    @abstractmethod
517    def publish_site_records(self, site_key: str, records: dict[str, list[int | float]]) -> ActivityUpdateResponseModel:
518        """ Publish a set of site records to inmotion
519
520        :param str site_key: The unique key of the site activity to publish records to
521        :param dict[str, list[int | float]] records: The records to publish, where
522        :return: The response from the publish of the records
523        :rtype: ActivityUpdateResponseModel
524        """
525        pass
526
527    @abstractmethod
528    def download_site_records(self, site_key: str, file_format: str) -> bytes:
529        """ Download the records of a site activity in the requested format
530
531        :param str site_key: The unique key of the site activity to download records from
532        :param str file_format: The format to download the records in ('csv', 'json' or 'gpx')
533        :return: The raw file content
534        :rtype: bytes
535        """
536        pass
537
538    @abstractmethod
539    def share_site_activity(self, site_key: str, kind: str) -> None:
540        """ Share a site activity
541
542        :param str site_key: The unique key of the site activity to share
543        :param str kind: The kind of sharing to apply ('any' or 'private')
544        """
545        pass
546
547    @abstractmethod
548    def unshare_site_activity(self, site_key: str, kind: str) -> None:
549        """ Remove sharing from a site activity
550
551        :param str site_key: The unique key of the site activity to unshare
552        :param str kind: The kind of sharing to revoke
553        """
554        pass
555
556    @abstractmethod
557    def find_shared_site_activity(self, site_key: str) -> SiteActivityModel:
558        """ Retrieve the details of a shared site activity
559
560        :param str site_key: The unique key of the shared site activity to retrieve
561        :return: The details of the shared site activity
562        :rtype: SiteActivityModel
563        """
564        pass
565
566    @abstractmethod
567    def find_shared_site_records(self, site_key: str, start_time: datetime, end_time: datetime) -> SiteRecordsModel:
568        """ Retrieve records of a shared site activity within the requested time-period
569
570        :param str site_key: The unique key of the shared site activity to retrieve records from
571        :param datetime start_time: The start of the time range (inclusive)
572        :param datetime end_time: The end of the time range (inclusive)
573        :return: The records for the shared site activity within the specified time range
574        :rtype: SiteRecordsModel
575        """
576        pass
577
578    @abstractmethod
579    def preview_site_records(self, site_key: str, qc_config: QCConfigModel) -> dict:
580        """ Retrieve records for a site activity with an ephemeral QC configuration applied. The
581        config is not saved.
582
583        :param str site_key: The unique key of the site activity to preview records for
584        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
585        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
586        :rtype: dict
587        """
588        pass
589
590    @abstractmethod
591    def preview_site_records_within_range(self, site_key: str, start_time: datetime, end_time: datetime, qc_config: QCConfigModel) -> dict:
592        """ Retrieve records for a site activity within a time range with an ephemeral QC
593        configuration applied. The config is not saved.
594
595        :param str site_key: The unique key of the site activity to preview records for
596        :param datetime start_time: The start of the time range (inclusive)
597        :param datetime end_time: The end of the time range (inclusive)
598        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
599        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
600        :rtype: dict
601        """
602        pass
603
604    @abstractmethod
605    def find_site_model_field_groups(self, site_key: str) -> list[ModelFieldGroupModel]:
606        """ Find a site activity's custom classification field values - one field group per
607        active classification tag on this site.
608
609        :param str site_key: The unique key of the site activity
610        :return: The site activity's active classification field groups
611        :rtype: list[ModelFieldGroupModel]
612        """
613        pass
614
615    @abstractmethod
616    def set_site_model_field_value(self, site_key: str, request: SetModelFieldValueRequestModel) -> list[ModelFieldGroupModel]:
617        """ Set (or, if value is omitted/blank on an optional field, clear) one custom
618        classification field's value for one active tag on a site activity.
619
620        :param str site_key: The unique key of the site activity
621        :param SetModelFieldValueRequestModel request: The field value to set
622        :return: The site activity's active classification field groups, including the updated value
623        :rtype: list[ModelFieldGroupModel]
624        """
625        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def find_activities( self, act_filter: inmotion.models.ActivitySearchFilterModel) -> inmotion.models.ActivitiesModel:
142    @abstractmethod
143    def find_activities(self, act_filter: ActivitySearchFilterModel) -> ActivitiesModel:
144        """
145        Retrieve all site based activities that contain observational data
146
147        :param ActivitySearchFilterModel act_filter: The filter to apply to the search
148        :return: The activities that match the filter
149        :rtype: ActivitiesModel
150        """
151        pass

Retrieve all site based activities that contain observational data

Parameters
  • ActivitySearchFilterModel act_filter: The filter to apply to the search
Returns

The activities that match the filter

@abstractmethod
def find_activities_within_time_range( self, act_filter: inmotion.models.ActivitySearchFilterModel, start: datetime.datetime, finish: datetime.datetime) -> inmotion.models.ActivitiesModel:
153    @abstractmethod
154    def find_activities_within_time_range(self, act_filter: ActivitySearchFilterModel, start: datetime, finish: datetime) -> ActivitiesModel:
155        """
156        Retrieve all site based activities that contain observational data within the specified time range.
157
158        :param ActivitySearchFilterModel act_filter: The filter to apply to the search
159        :param datetime start: The start of the time range (inclusive)
160        :param datetime finish: The end of the time range (inclusive)
161        :return: The activities that match the filter and time range
162        :rtype: ActivitiesModel
163        """
164        pass

Retrieve all site based activities that contain observational data within the specified time range.

Parameters
  • ActivitySearchFilterModel act_filter: The filter to apply to the search
  • datetime start: The start of the time range (inclusive)
  • datetime finish: The end of the time range (inclusive)
Returns

The activities that match the filter and time range

@abstractmethod
def find_latest_activity_stats( self, since: datetime.datetime, lite: bool = False) -> inmotion.models.LastActivitiesModel:
166    @abstractmethod
167    def find_latest_activity_stats(self, since: datetime, lite: bool = False) -> LastActivitiesModel:
168        """ Retrieve the latest records for all activities since the provided date
169
170        :param datetime since: The date/time to search from
171        :param bool lite: If true, each sensor carries only its last value, without the statistics over the window
172        :return: The latest activities since the specified date
173        :rtype: LastActivitiesModel
174        """
175        pass

Retrieve the latest records for all activities since the provided date

Parameters
  • datetime since: The date/time to search from
  • bool lite: If true, each sensor carries only its last value, without the statistics over the window
Returns

The latest activities since the specified date

@abstractmethod
def find_latest_activity_stats_by_type( self, since: datetime.datetime, coord_conv: str, lite: bool = False) -> inmotion.models.LastActivitiesModel:
177    @abstractmethod
178    def find_latest_activity_stats_by_type(self, since: datetime, coord_conv: str, lite: bool = False) -> LastActivitiesModel:
179        """ Retrieve the latest records for all activities of a specific Coordinate Convention since the provided date
180
181        :param datetime since: The date/time to search from
182        :param str coord_conv: The Coordinate Convention to restrict results to (see CoordinateConvention)
183        :param bool lite: If true, each sensor carries only its last value, without the statistics over the window
184        :return: The latest activities since the specified date
185        :rtype: LastActivitiesModel
186        """
187        pass

Retrieve the latest records for all activities of a specific Coordinate Convention since the provided date

Parameters
  • datetime since: The date/time to search from
  • str coord_conv: The Coordinate Convention to restrict results to (see CoordinateConvention)
  • bool lite: If true, each sensor carries only its last value, without the statistics over the window
Returns

The latest activities since the specified date

@abstractmethod
def find_activity_master_data(self) -> inmotion.models.MasterDataModel:
189    @abstractmethod
190    def find_activity_master_data(self) -> MasterDataModel:
191        """ Fetch master data related to activities (profile types and activity types)
192
193        :return: The activity master data
194        :rtype: MasterDataModel
195        """
196        pass

Fetch master data related to activities (profile types and activity types)

Returns

The activity master data

@abstractmethod
def find_activity_analytics( self, request: inmotion.models.ActivityAnalyticsRequestModel) -> inmotion.models.ActivityAnalyticsResultModel:
198    @abstractmethod
199    def find_activity_analytics(self, request: ActivityAnalyticsRequestModel) -> ActivityAnalyticsResultModel:
200        """ Retrieve grouped activity counts across one or more accounts (or, if none are
201        supplied, every account the caller can access)
202
203        :param ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
204        :return: The grouped activity counts
205        :rtype: ActivityAnalyticsResultModel
206        """
207        pass

Retrieve grouped activity counts across one or more accounts (or, if none are supplied, every account the caller can access)

Parameters
  • ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
Returns

The grouped activity counts

@abstractmethod
def find_activity_track_metrics( self, request: inmotion.models.ActivityAnalyticsRequestModel) -> inmotion.models.ActivityTrackMetricsResultModel:
209    @abstractmethod
210    def find_activity_track_metrics(self, request: ActivityAnalyticsRequestModel) -> ActivityTrackMetricsResultModel:
211        """ Retrieve aggregate track metrics (distance/ascent/descent/duration/speed) across one
212        or more accounts, for TRACK-kind activities only
213
214        :param ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
215        :return: The grouped track metrics
216        :rtype: ActivityTrackMetricsResultModel
217        """
218        pass

Retrieve aggregate track metrics (distance/ascent/descent/duration/speed) across one or more accounts, for TRACK-kind activities only

Parameters
  • ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
Returns

The grouped track metrics

@abstractmethod
def find_activity_variable_stats( self, request: inmotion.models.ActivityAnalyticsRequestModel) -> inmotion.models.ActivityVariableStatsResultModel:
220    @abstractmethod
221    def find_activity_variable_stats(self, request: ActivityAnalyticsRequestModel) -> ActivityVariableStatsResultModel:
222        """ Retrieve aggregate, per-standard-data-type variable statistics across one or more
223        accounts, for TRACK-kind activities only
224
225        :param ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
226        :return: The grouped variable statistics
227        :rtype: ActivityVariableStatsResultModel
228        """
229        pass

Retrieve aggregate, per-standard-data-type variable statistics across one or more accounts, for TRACK-kind activities only

Parameters
  • ActivityAnalyticsRequestModel request: The accounts, filter, and grouping to apply
Returns

The grouped variable statistics

@abstractmethod
def batch_record_update( self, commands: inmotion.models.ActivityBatchCommandsModel) -> list[inmotion.models.ActivityBatchResultModel]:
231    @abstractmethod
232    def batch_record_update(self, commands: ActivityBatchCommandsModel) -> list[ActivityBatchResultModel]:
233        """ Apply a batch of track and/or site activity create/update commands in a single request
234
235        :param ActivityBatchCommandsModel commands: The batch of track and/or site commands to apply
236        :return: The per-command results, matched back to their command via `seqKey`
237        :rtype: list[ActivityBatchResultModel]
238        """
239        pass

Apply a batch of track and/or site activity create/update commands in a single request

Parameters
  • ActivityBatchCommandsModel commands: The batch of track and/or site commands to apply
Returns

The per-command results, matched back to their command via seqKey

@abstractmethod
def create_track_activity( self, activity: inmotion.models.CreateTrackActivityModel) -> inmotion.models.ActivityUpdateResponseModel:
241    @abstractmethod
242    def create_track_activity(self, activity: CreateTrackActivityModel) -> ActivityUpdateResponseModel:
243        """ Create a track activity based on the definition
244
245        :param CreateTrackActivityModel activity: The definition of the track activity to create
246        :return: The response from the creation of the activity
247        :rtype: ActivityUpdateResponseModel
248        """
249        pass

Create a track activity based on the definition

Parameters
  • CreateTrackActivityModel activity: The definition of the track activity to create
Returns

The response from the creation of the activity

@abstractmethod
def update_track_activity( self, track_key: str, activity: inmotion.models.UpdateTrackActivityModel) -> inmotion.models.ActivityUpdateResponseModel:
251    @abstractmethod
252    def update_track_activity(self, track_key: str, activity: UpdateTrackActivityModel) -> ActivityUpdateResponseModel:
253        """ Update a track activity based on the definition
254
255        :param str track_key: The unique key of the track activity to update
256        :param UpdateTrackActivityModel activity: The updated definition of the track activity
257        :return: The response from the update of the activity
258        """
259        pass

Update a track activity based on the definition

Parameters
  • str track_key: The unique key of the track activity to update
  • UpdateTrackActivityModel activity: The updated definition of the track activity
Returns

The response from the update of the activity

@abstractmethod
def find_track_activity(self, track_key: str) -> inmotion.models.TrackActivityModel:
261    @abstractmethod
262    def find_track_activity(self, track_key: str) -> TrackActivityModel:
263        """ Retrieve the details for the requested inMotion track
264
265        :param str track_key: The unique key of the track activity to retrieve
266        :return: The details of the track activity
267        :rtype: TrackActivityDetails
268        """
269        pass

Retrieve the details for the requested inMotion track

Parameters
  • str track_key: The unique key of the track activity to retrieve
Returns

The details of the track activity

@abstractmethod
def delete_track_activity(self, track_key: str) -> None:
271    @abstractmethod
272    def delete_track_activity(self, track_key: str) -> None:
273        """ Delete a track activity and all of its associated records
274
275        :param str track_key: The unique key of the track activity to delete
276        """
277        pass

Delete a track activity and all of its associated records

Parameters
  • str track_key: The unique key of the track activity to delete
@abstractmethod
def finish_track_activity(self, track_key: str) -> None:
279    @abstractmethod
280    def finish_track_activity(self, track_key: str) -> None:
281        """ Make a track that was created with ``uploadState="uploading"`` visible, once all its records are sent
282
283        :param str track_key: The unique key of the track activity to finish
284        """
285        pass

Make a track that was created with uploadState="uploading" visible, once all its records are sent

Parameters
  • str track_key: The unique key of the track activity to finish
@abstractmethod
def unlock_track_activity(self, track_key: str) -> None:
287    @abstractmethod
288    def unlock_track_activity(self, track_key: str) -> None:
289        """ Unlock a track activity so that it can be modified or updated
290
291        :param str track_key: The unique key of the track activity to unlock
292        """
293        pass

Unlock a track activity so that it can be modified or updated

Parameters
  • str track_key: The unique key of the track activity to unlock
@abstractmethod
def get_track_records( self, track_key: str, start_time: Optional[datetime.datetime], end_time: Optional[datetime.datetime]) -> inmotion.models.TrackRecordsModel:
295    @abstractmethod
296    def get_track_records(self, track_key: str, start_time: Optional[datetime], end_time: Optional[datetime]) -> TrackRecordsModel:
297        """ Retrieve records from inMotion within the requested time-period
298
299        :param str track_key: The unique key of the track activity to retrieve records from
300        :param Optional[datetime] start_time: The start of the time range (inclusive)
301        :param Optional[datetime] end_time: The end of the time range (inclusive)
302        :return: The records for the track activity within the specified time range
303        :rtype: TrackRecords
304        """
305        pass

Retrieve records from inMotion within the requested time-period

Parameters
  • str track_key: The unique key of the track activity to retrieve records from
  • Optional[datetime] start_time: The start of the time range (inclusive)
  • Optional[datetime] end_time: The end of the time range (inclusive)
Returns

The records for the track activity within the specified time range

@abstractmethod
def find_all_track_records( self, track_key: str, after: Optional[datetime.datetime] = None) -> inmotion.models.TrackRecordsModel:
307    @abstractmethod
308    def find_all_track_records(self, track_key: str, after: Optional[datetime] = None) -> TrackRecordsModel:
309        """ Retrieve the records for a track activity, without an upper time restriction
310
311        :param str track_key: The unique key of the track activity to retrieve records from
312        :param Optional[datetime] after: If given, only records recorded after this time are returned. The
313            statistics and markers are still those of the whole track, and `lastRecorded` on the result
314            gives the time of the track's final record - pass it back as `after` to poll for new records.
315        :return: The records for the track activity
316        :rtype: TrackRecordsModel
317        """
318        pass

Retrieve the records for a track activity, without an upper time restriction

Parameters
  • str track_key: The unique key of the track activity to retrieve records from
  • Optional[datetime] after: If given, only records recorded after this time are returned. The statistics and markers are still those of the whole track, and lastRecorded on the result gives the time of the track's final record - pass it back as after to poll for new records.
Returns

The records for the track activity

@abstractmethod
def publish_track_records( self, track_key: str, records: dict[str, list[int | float]]) -> inmotion.models.ActivityUpdateResponseModel:
320    @abstractmethod
321    def publish_track_records(self, track_key: str, records: dict[str, list[int | float]]) -> ActivityUpdateResponseModel:
322        """ Publish a set of track records to inmotion
323
324        :param str track_key: The unique key of the track activity to publish records to
325        :param dict[str, list[int | float]] records: The records to publish, where the key is the field name and the value is a list of values
326        :return: The response from the publish of the records
327        :rtype: ActivityUpdateResponseModel
328        """
329        pass

Publish a set of track records to inmotion

Parameters
  • str track_key: The unique key of the track activity to publish records to
  • dict[str, list[int | float]] records: The records to publish, where the key is the field name and the value is a list of values
Returns

The response from the publish of the records

@abstractmethod
def download_track_records(self, track_key: str, file_format: str) -> bytes:
331    @abstractmethod
332    def download_track_records(self, track_key: str, file_format: str) -> bytes:
333        """ Download the records of a track activity in the requested format
334
335        :param str track_key: The unique key of the track activity to download records from
336        :param str file_format: The format to download the records in ('csv', 'json' or 'gpx')
337        :return: The raw file content
338        :rtype: bytes
339        """
340        pass

Download the records of a track activity in the requested format

Parameters
  • str track_key: The unique key of the track activity to download records from
  • str file_format: The format to download the records in ('csv', 'json' or 'gpx')
Returns

The raw file content

@abstractmethod
def share_track_activity(self, track_key: str, kind: str) -> None:
342    @abstractmethod
343    def share_track_activity(self, track_key: str, kind: str) -> None:
344        """ Share a track activity
345
346        :param str track_key: The unique key of the track activity to share
347        :param str kind: The kind of sharing to apply ('any' or 'private')
348        """
349        pass

Share a track activity

Parameters
  • str track_key: The unique key of the track activity to share
  • str kind: The kind of sharing to apply ('any' or 'private')
@abstractmethod
def unshare_track_activity(self, track_key: str, kind: str) -> None:
351    @abstractmethod
352    def unshare_track_activity(self, track_key: str, kind: str) -> None:
353        """ Remove sharing from a track activity
354
355        :param str track_key: The unique key of the track activity to unshare
356        :param str kind: The kind of sharing to revoke
357        """
358        pass

Remove sharing from a track activity

Parameters
  • str track_key: The unique key of the track activity to unshare
  • str kind: The kind of sharing to revoke
@abstractmethod
def find_shared_track_activity(self, track_key: str) -> inmotion.models.TrackActivityModel:
360    @abstractmethod
361    def find_shared_track_activity(self, track_key: str) -> TrackActivityModel:
362        """ Retrieve the details of a shared track activity
363
364        :param str track_key: The unique key of the shared track activity to retrieve
365        :return: The details of the shared track activity
366        :rtype: TrackActivityModel
367        """
368        pass

Retrieve the details of a shared track activity

Parameters
  • str track_key: The unique key of the shared track activity to retrieve
Returns

The details of the shared track activity

@abstractmethod
def find_all_shared_track_records(self, track_key: str) -> inmotion.models.TrackRecordsModel:
370    @abstractmethod
371    def find_all_shared_track_records(self, track_key: str) -> TrackRecordsModel:
372        """ Retrieve all records of a shared track activity
373
374        :param str track_key: The unique key of the shared track activity to retrieve records from
375        :return: All records for the shared track activity
376        :rtype: TrackRecordsModel
377        """
378        pass

Retrieve all records of a shared track activity

Parameters
  • str track_key: The unique key of the shared track activity to retrieve records from
Returns

All records for the shared track activity

@abstractmethod
def convert_track_to_route(self, track_key: str, name: Optional[str] = None) -> str:
380    @abstractmethod
381    def convert_track_to_route(self, track_key: str, name: Optional[str] = None) -> str:
382        """ Create a new, standalone Coverage/Route Shape from a track activity's GPS records.
383        The original track is left untouched - this is a derived record, not an in-place nature
384        change. Gated by the "track-to-shape" account feature.
385
386        :param str track_key: The unique key of the track activity to convert
387        :param Optional[str] name: An optional name for the new Route shape. Defaults to
388            "<track name> (Route)" when omitted.
389        :return: The new shape's key
390        :rtype: str
391        """
392        pass

Create a new, standalone Coverage/Route Shape from a track activity's GPS records. The original track is left untouched - this is a derived record, not an in-place nature change. Gated by the "track-to-shape" account feature.

Parameters
  • str track_key: The unique key of the track activity to convert
  • Optional[str] name: An optional name for the new Route shape. Defaults to " (Route)" when omitted.
Returns

The new shape's key

@abstractmethod
def preview_track_records(self, track_key: str, qc_config: inmotion.models.QCConfigModel) -> dict:
394    @abstractmethod
395    def preview_track_records(self, track_key: str, qc_config: QCConfigModel) -> dict:
396        """ Retrieve records for a track activity with an ephemeral QC configuration applied. The
397        config is not saved.
398
399        :param str track_key: The unique key of the track activity to preview records for
400        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
401        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
402        :rtype: dict
403        """
404        pass

Retrieve records for a track activity with an ephemeral QC configuration applied. The config is not saved.

Parameters
  • str track_key: The unique key of the track activity to preview records for
  • QCConfigModel qc_config: The ephemeral QC configuration to apply
Returns

The previewed records, as a raw dict (no fixed schema is declared server-side)

@abstractmethod
def preview_track_records_within_range( self, track_key: str, start_time: datetime.datetime, end_time: datetime.datetime, qc_config: inmotion.models.QCConfigModel) -> dict:
406    @abstractmethod
407    def preview_track_records_within_range(self, track_key: str, start_time: datetime, end_time: datetime, qc_config: QCConfigModel) -> dict:
408        """ Retrieve records for a track activity within a time range with an ephemeral QC
409        configuration applied. The config is not saved.
410
411        :param str track_key: The unique key of the track activity to preview records for
412        :param datetime start_time: The start of the time range (inclusive)
413        :param datetime end_time: The end of the time range (inclusive)
414        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
415        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
416        :rtype: dict
417        """
418        pass

Retrieve records for a track activity within a time range with an ephemeral QC configuration applied. The config is not saved.

Parameters
  • str track_key: The unique key of the track activity to preview records for
  • datetime start_time: The start of the time range (inclusive)
  • datetime end_time: The end of the time range (inclusive)
  • QCConfigModel qc_config: The ephemeral QC configuration to apply
Returns

The previewed records, as a raw dict (no fixed schema is declared server-side)

@abstractmethod
def find_track_model_field_groups(self, track_key: str) -> list[inmotion.models.ModelFieldGroupModel]:
420    @abstractmethod
421    def find_track_model_field_groups(self, track_key: str) -> list[ModelFieldGroupModel]:
422        """ Find a track activity's custom classification field values - one field group per
423        active classification tag on this track.
424
425        :param str track_key: The unique key of the track activity
426        :return: The track activity's active classification field groups
427        :rtype: list[ModelFieldGroupModel]
428        """
429        pass

Find a track activity's custom classification field values - one field group per active classification tag on this track.

Parameters
  • str track_key: The unique key of the track activity
Returns

The track activity's active classification field groups

@abstractmethod
def set_track_model_field_value( self, track_key: str, request: inmotion.models.SetModelFieldValueRequestModel) -> list[inmotion.models.ModelFieldGroupModel]:
431    @abstractmethod
432    def set_track_model_field_value(self, track_key: str, request: SetModelFieldValueRequestModel) -> list[ModelFieldGroupModel]:
433        """ Set (or, if value is omitted/blank on an optional field, clear) one custom
434        classification field's value for one active tag on a track activity.
435
436        :param str track_key: The unique key of the track activity
437        :param SetModelFieldValueRequestModel request: The field value to set
438        :return: The track activity's active classification field groups, including the updated value
439        :rtype: list[ModelFieldGroupModel]
440        """
441        pass

Set (or, if value is omitted/blank on an optional field, clear) one custom classification field's value for one active tag on a track activity.

Parameters
  • str track_key: The unique key of the track activity
  • SetModelFieldValueRequestModel request: The field value to set
Returns

The track activity's active classification field groups, including the updated value

@abstractmethod
def create_site_activity( self, activity: inmotion.models.CreateSiteActivityModel) -> inmotion.models.ActivityUpdateResponseModel:
443    @abstractmethod
444    def create_site_activity(self, activity: CreateSiteActivityModel) -> ActivityUpdateResponseModel:
445        """ Create a site activity based on the definition
446
447        :param CreateSiteActivityModel activity: The definition of the site activity to create
448        :return: The response from the creation of the activity
449        :rtype: ActivityUpdateResponseModel
450        """
451        pass

Create a site activity based on the definition

Parameters
  • CreateSiteActivityModel activity: The definition of the site activity to create
Returns

The response from the creation of the activity

@abstractmethod
def update_site_activity( self, site_key: str, activity: inmotion.models.UpdateSiteActivityModel) -> inmotion.models.ActivityUpdateResponseModel:
453    @abstractmethod
454    def update_site_activity(self, site_key: str, activity: UpdateSiteActivityModel) -> ActivityUpdateResponseModel:
455        """ Update a site activity based on the definition
456
457        :param str site_key: The unique key of the site activity to update
458        :param UpdateSiteActivityModel activity: The updated definition of the site activity
459        :return: The response from the update of the activity
460        :rtype: ActivityUpdateResponseModel
461        """
462        pass

Update a site activity based on the definition

Parameters
  • str site_key: The unique key of the site activity to update
  • UpdateSiteActivityModel activity: The updated definition of the site activity
Returns

The response from the update of the activity

@abstractmethod
def find_site_activity(self, site_key: str) -> inmotion.models.SiteActivityModel:
464    @abstractmethod
465    def find_site_activity(self, site_key: str) -> SiteActivityModel:
466        """ Retrieve the details for the requested inMotion site
467
468        :param str site_key: The unique key of the site activity to retrieve
469        :return: The details of the site activity
470        :rtype: SiteActivityModel
471
472        """
473        pass

Retrieve the details for the requested inMotion site

Parameters
  • str site_key: The unique key of the site activity to retrieve
Returns

The details of the site activity

@abstractmethod
def delete_site_activity(self, site_key: str) -> None:
475    @abstractmethod
476    def delete_site_activity(self, site_key: str) -> None:
477        """ Delete a site activity and all of its associated records
478
479        :param str site_key: The unique key of the site activity to delete
480        """
481        pass

Delete a site activity and all of its associated records

Parameters
  • str site_key: The unique key of the site activity to delete
@abstractmethod
def unlock_site_activity(self, site_key: str) -> None:
483    @abstractmethod
484    def unlock_site_activity(self, site_key: str) -> None:
485        """ Unlock a site activity so that it can be modified or updated
486
487        :param str site_key: The unique key of the site activity to unlock
488        """
489        pass

Unlock a site activity so that it can be modified or updated

Parameters
  • str site_key: The unique key of the site activity to unlock
@abstractmethod
def get_site_records( self, site_key: str, start_time: Optional[datetime.datetime], end_time: Optional[datetime.datetime]) -> inmotion.models.SiteRecordsModel:
491    @abstractmethod
492    def get_site_records(self, site_key: str, start_time: Optional[datetime], end_time: Optional[datetime]) -> SiteRecordsModel:
493        """ Retrieve records from inMotion within the requested time-period
494
495        :param str site_key: The unique key of the site activity to retrieve records from
496        :param Optional[datetime] start_time: The start of the time range (inclusive)
497        :param Optional[datetime] end_time: The end of the time range (inclusive)
498        :return: The records for the site activity within the specified time range
499        :rtype: SiteRecords
500        """
501        pass

Retrieve records from inMotion within the requested time-period

Parameters
  • str site_key: The unique key of the site activity to retrieve records from
  • Optional[datetime] start_time: The start of the time range (inclusive)
  • Optional[datetime] end_time: The end of the time range (inclusive)
Returns

The records for the site activity within the specified time range

@abstractmethod
def find_all_site_records( self, site_key: str, after: Optional[datetime.datetime] = None) -> inmotion.models.SiteRecordsModel:
503    @abstractmethod
504    def find_all_site_records(self, site_key: str, after: Optional[datetime] = None) -> SiteRecordsModel:
505        """ Retrieve all records for a site activity, without a time range restriction
506
507        :param str site_key: The unique key of the site activity to retrieve records from
508        :param Optional[datetime] after: If given, only records recorded after this time are returned. The
509            statistics are still those of all the records, and `lastRecorded` on the result gives the time
510            of the final record - pass it back as `after` to poll for new records.
511        :return: All records for the site activity
512        :rtype: SiteRecordsModel
513        """
514        pass

Retrieve all records for a site activity, without a time range restriction

Parameters
  • str site_key: The unique key of the site activity to retrieve records from
  • Optional[datetime] after: If given, only records recorded after this time are returned. The statistics are still those of all the records, and lastRecorded on the result gives the time of the final record - pass it back as after to poll for new records.
Returns

All records for the site activity

@abstractmethod
def publish_site_records( self, site_key: str, records: dict[str, list[int | float]]) -> inmotion.models.ActivityUpdateResponseModel:
516    @abstractmethod
517    def publish_site_records(self, site_key: str, records: dict[str, list[int | float]]) -> ActivityUpdateResponseModel:
518        """ Publish a set of site records to inmotion
519
520        :param str site_key: The unique key of the site activity to publish records to
521        :param dict[str, list[int | float]] records: The records to publish, where
522        :return: The response from the publish of the records
523        :rtype: ActivityUpdateResponseModel
524        """
525        pass

Publish a set of site records to inmotion

Parameters
  • str site_key: The unique key of the site activity to publish records to
  • dict[str, list[int | float]] records: The records to publish, where
Returns

The response from the publish of the records

@abstractmethod
def download_site_records(self, site_key: str, file_format: str) -> bytes:
527    @abstractmethod
528    def download_site_records(self, site_key: str, file_format: str) -> bytes:
529        """ Download the records of a site activity in the requested format
530
531        :param str site_key: The unique key of the site activity to download records from
532        :param str file_format: The format to download the records in ('csv', 'json' or 'gpx')
533        :return: The raw file content
534        :rtype: bytes
535        """
536        pass

Download the records of a site activity in the requested format

Parameters
  • str site_key: The unique key of the site activity to download records from
  • str file_format: The format to download the records in ('csv', 'json' or 'gpx')
Returns

The raw file content

@abstractmethod
def share_site_activity(self, site_key: str, kind: str) -> None:
538    @abstractmethod
539    def share_site_activity(self, site_key: str, kind: str) -> None:
540        """ Share a site activity
541
542        :param str site_key: The unique key of the site activity to share
543        :param str kind: The kind of sharing to apply ('any' or 'private')
544        """
545        pass

Share a site activity

Parameters
  • str site_key: The unique key of the site activity to share
  • str kind: The kind of sharing to apply ('any' or 'private')
@abstractmethod
def unshare_site_activity(self, site_key: str, kind: str) -> None:
547    @abstractmethod
548    def unshare_site_activity(self, site_key: str, kind: str) -> None:
549        """ Remove sharing from a site activity
550
551        :param str site_key: The unique key of the site activity to unshare
552        :param str kind: The kind of sharing to revoke
553        """
554        pass

Remove sharing from a site activity

Parameters
  • str site_key: The unique key of the site activity to unshare
  • str kind: The kind of sharing to revoke
@abstractmethod
def find_shared_site_activity(self, site_key: str) -> inmotion.models.SiteActivityModel:
556    @abstractmethod
557    def find_shared_site_activity(self, site_key: str) -> SiteActivityModel:
558        """ Retrieve the details of a shared site activity
559
560        :param str site_key: The unique key of the shared site activity to retrieve
561        :return: The details of the shared site activity
562        :rtype: SiteActivityModel
563        """
564        pass

Retrieve the details of a shared site activity

Parameters
  • str site_key: The unique key of the shared site activity to retrieve
Returns

The details of the shared site activity

@abstractmethod
def find_shared_site_records( self, site_key: str, start_time: datetime.datetime, end_time: datetime.datetime) -> inmotion.models.SiteRecordsModel:
566    @abstractmethod
567    def find_shared_site_records(self, site_key: str, start_time: datetime, end_time: datetime) -> SiteRecordsModel:
568        """ Retrieve records of a shared site activity within the requested time-period
569
570        :param str site_key: The unique key of the shared site activity to retrieve records from
571        :param datetime start_time: The start of the time range (inclusive)
572        :param datetime end_time: The end of the time range (inclusive)
573        :return: The records for the shared site activity within the specified time range
574        :rtype: SiteRecordsModel
575        """
576        pass

Retrieve records of a shared site activity within the requested time-period

Parameters
  • str site_key: The unique key of the shared site activity to retrieve records from
  • datetime start_time: The start of the time range (inclusive)
  • datetime end_time: The end of the time range (inclusive)
Returns

The records for the shared site activity within the specified time range

@abstractmethod
def preview_site_records(self, site_key: str, qc_config: inmotion.models.QCConfigModel) -> dict:
578    @abstractmethod
579    def preview_site_records(self, site_key: str, qc_config: QCConfigModel) -> dict:
580        """ Retrieve records for a site activity with an ephemeral QC configuration applied. The
581        config is not saved.
582
583        :param str site_key: The unique key of the site activity to preview records for
584        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
585        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
586        :rtype: dict
587        """
588        pass

Retrieve records for a site activity with an ephemeral QC configuration applied. The config is not saved.

Parameters
  • str site_key: The unique key of the site activity to preview records for
  • QCConfigModel qc_config: The ephemeral QC configuration to apply
Returns

The previewed records, as a raw dict (no fixed schema is declared server-side)

@abstractmethod
def preview_site_records_within_range( self, site_key: str, start_time: datetime.datetime, end_time: datetime.datetime, qc_config: inmotion.models.QCConfigModel) -> dict:
590    @abstractmethod
591    def preview_site_records_within_range(self, site_key: str, start_time: datetime, end_time: datetime, qc_config: QCConfigModel) -> dict:
592        """ Retrieve records for a site activity within a time range with an ephemeral QC
593        configuration applied. The config is not saved.
594
595        :param str site_key: The unique key of the site activity to preview records for
596        :param datetime start_time: The start of the time range (inclusive)
597        :param datetime end_time: The end of the time range (inclusive)
598        :param QCConfigModel qc_config: The ephemeral QC configuration to apply
599        :return: The previewed records, as a raw dict (no fixed schema is declared server-side)
600        :rtype: dict
601        """
602        pass

Retrieve records for a site activity within a time range with an ephemeral QC configuration applied. The config is not saved.

Parameters
  • str site_key: The unique key of the site activity to preview records for
  • datetime start_time: The start of the time range (inclusive)
  • datetime end_time: The end of the time range (inclusive)
  • QCConfigModel qc_config: The ephemeral QC configuration to apply
Returns

The previewed records, as a raw dict (no fixed schema is declared server-side)

@abstractmethod
def find_site_model_field_groups(self, site_key: str) -> list[inmotion.models.ModelFieldGroupModel]:
604    @abstractmethod
605    def find_site_model_field_groups(self, site_key: str) -> list[ModelFieldGroupModel]:
606        """ Find a site activity's custom classification field values - one field group per
607        active classification tag on this site.
608
609        :param str site_key: The unique key of the site activity
610        :return: The site activity's active classification field groups
611        :rtype: list[ModelFieldGroupModel]
612        """
613        pass

Find a site activity's custom classification field values - one field group per active classification tag on this site.

Parameters
  • str site_key: The unique key of the site activity
Returns

The site activity's active classification field groups

@abstractmethod
def set_site_model_field_value( self, site_key: str, request: inmotion.models.SetModelFieldValueRequestModel) -> list[inmotion.models.ModelFieldGroupModel]:
615    @abstractmethod
616    def set_site_model_field_value(self, site_key: str, request: SetModelFieldValueRequestModel) -> list[ModelFieldGroupModel]:
617        """ Set (or, if value is omitted/blank on an optional field, clear) one custom
618        classification field's value for one active tag on a site activity.
619
620        :param str site_key: The unique key of the site activity
621        :param SetModelFieldValueRequestModel request: The field value to set
622        :return: The site activity's active classification field groups, including the updated value
623        :rtype: list[ModelFieldGroupModel]
624        """
625        pass

Set (or, if value is omitted/blank on an optional field, clear) one custom classification field's value for one active tag on a site activity.

Parameters
  • str site_key: The unique key of the site activity
  • SetModelFieldValueRequestModel request: The field value to set
Returns

The site activity's active classification field groups, including the updated value

class InMotionActivityConfig(abc.ABC):
1180class InMotionActivityConfig(ABC):
1181    @abstractmethod
1182    def find_activity_config(self, key: str) -> ActivityConfigModel:
1183        """ Retrieve the complete activity configuration (QC, Processing, Custom Data, and History)
1184
1185        :param str key: The unique key of the activity
1186        :return: The full activity configuration
1187        :rtype: ActivityConfigModel
1188        """
1189        pass
1190
1191    @abstractmethod
1192    def update_qc_config(self, key: str, qc_update: ActivityConfigQCUpdateModel) -> ActivityConfigModel:
1193        """ Replace the Quality Control section of an activity's configuration
1194
1195        :param str key: The unique key of the activity
1196        :param ActivityConfigQCUpdateModel qc_update: The replacement QC configuration
1197        :return: The updated full activity configuration
1198        :rtype: ActivityConfigModel
1199        """
1200        pass
1201
1202    @abstractmethod
1203    def update_processing_config(self, key: str, processing_update: ActivityConfigProcessingUpdateModel) -> ActivityConfigModel:
1204        """ Replace the Processing section of an activity's configuration
1205
1206        :param str key: The unique key of the activity
1207        :param ActivityConfigProcessingUpdateModel processing_update: The replacement processing configuration
1208        :return: The updated full activity configuration
1209        :rtype: ActivityConfigModel
1210        """
1211        pass
1212
1213    @abstractmethod
1214    def update_custom_data_config(self, key: str, custom_data_update: ActivityConfigCustomDataUpdateModel) -> ActivityConfigModel:
1215        """ Replace the Custom Data section of an activity's configuration
1216
1217        :param str key: The unique key of the activity
1218        :param ActivityConfigCustomDataUpdateModel custom_data_update: The replacement custom data entries
1219        :return: The updated full activity configuration
1220        :rtype: ActivityConfigModel
1221        """
1222        pass
1223
1224    @abstractmethod
1225    def delete_activity_config(self, key: str) -> ActivityConfigDeleteResponseModel:
1226        """ Delete the entire activity configuration for an activity
1227
1228        :param str key: The unique key of the activity
1229        :return: The result of the delete operation
1230        :rtype: ActivityConfigDeleteResponseModel
1231        """
1232        pass
1233
1234    @abstractmethod
1235    def detect_bad_periods(self, key: str, request: ActivityConfigBadPeriodDetectRequestModel) -> ActivityConfigBadPeriodDetectResultModel:
1236        """ Run GPS-spike analysis on a track activity's raw data to detect candidate bad-time periods
1237
1238        :param str key: The unique key of the (track) activity
1239        :param ActivityConfigBadPeriodDetectRequestModel request: An optional time window to constrain detection
1240        :return: The detected candidate bad periods
1241        :rtype: ActivityConfigBadPeriodDetectResultModel
1242        """
1243        pass
1244
1245    @abstractmethod
1246    def merge_bad_periods(self, key: str, request: ActivityConfigBadPeriodMergeRequestModel) -> ActivityConfigBadPeriodMergeResultModel:
1247        """ Merge bad periods into the Quality Control section of an activity's configuration
1248
1249        :param str key: The unique key of the activity
1250        :param ActivityConfigBadPeriodMergeRequestModel request: The periods to merge, and whether this is a dry run
1251        :return: The resulting QC config YAML and merge metadata
1252        :rtype: ActivityConfigBadPeriodMergeResultModel
1253        """
1254        pass
1255
1256    @abstractmethod
1257    def generate_qc_regions(self, key: str, request: ActivityConfigQCRegionGenerateRequestModel) -> ActivityConfigQCRegionGenerateResultModel:
1258        """ Analyze an activity's raw data and generate candidate, labelled QC regions
1259
1260        :param str key: The unique key of the activity
1261        :param ActivityConfigQCRegionGenerateRequestModel request: An optional time window to constrain detection
1262        :return: The generated candidate QC regions
1263        :rtype: ActivityConfigQCRegionGenerateResultModel
1264        """
1265        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def find_activity_config(self, key: str) -> inmotion.models.ActivityConfigModel:
1181    @abstractmethod
1182    def find_activity_config(self, key: str) -> ActivityConfigModel:
1183        """ Retrieve the complete activity configuration (QC, Processing, Custom Data, and History)
1184
1185        :param str key: The unique key of the activity
1186        :return: The full activity configuration
1187        :rtype: ActivityConfigModel
1188        """
1189        pass

Retrieve the complete activity configuration (QC, Processing, Custom Data, and History)

Parameters
  • str key: The unique key of the activity
Returns

The full activity configuration

@abstractmethod
def update_qc_config( self, key: str, qc_update: inmotion.models.ActivityConfigQCUpdateModel) -> inmotion.models.ActivityConfigModel:
1191    @abstractmethod
1192    def update_qc_config(self, key: str, qc_update: ActivityConfigQCUpdateModel) -> ActivityConfigModel:
1193        """ Replace the Quality Control section of an activity's configuration
1194
1195        :param str key: The unique key of the activity
1196        :param ActivityConfigQCUpdateModel qc_update: The replacement QC configuration
1197        :return: The updated full activity configuration
1198        :rtype: ActivityConfigModel
1199        """
1200        pass

Replace the Quality Control section of an activity's configuration

Parameters
  • str key: The unique key of the activity
  • ActivityConfigQCUpdateModel qc_update: The replacement QC configuration
Returns

The updated full activity configuration

@abstractmethod
def update_processing_config( self, key: str, processing_update: inmotion.models.ActivityConfigProcessingUpdateModel) -> inmotion.models.ActivityConfigModel:
1202    @abstractmethod
1203    def update_processing_config(self, key: str, processing_update: ActivityConfigProcessingUpdateModel) -> ActivityConfigModel:
1204        """ Replace the Processing section of an activity's configuration
1205
1206        :param str key: The unique key of the activity
1207        :param ActivityConfigProcessingUpdateModel processing_update: The replacement processing configuration
1208        :return: The updated full activity configuration
1209        :rtype: ActivityConfigModel
1210        """
1211        pass

Replace the Processing section of an activity's configuration

Parameters
  • str key: The unique key of the activity
  • ActivityConfigProcessingUpdateModel processing_update: The replacement processing configuration
Returns

The updated full activity configuration

@abstractmethod
def update_custom_data_config( self, key: str, custom_data_update: inmotion.models.ActivityConfigCustomDataUpdateModel) -> inmotion.models.ActivityConfigModel:
1213    @abstractmethod
1214    def update_custom_data_config(self, key: str, custom_data_update: ActivityConfigCustomDataUpdateModel) -> ActivityConfigModel:
1215        """ Replace the Custom Data section of an activity's configuration
1216
1217        :param str key: The unique key of the activity
1218        :param ActivityConfigCustomDataUpdateModel custom_data_update: The replacement custom data entries
1219        :return: The updated full activity configuration
1220        :rtype: ActivityConfigModel
1221        """
1222        pass

Replace the Custom Data section of an activity's configuration

Parameters
  • str key: The unique key of the activity
  • ActivityConfigCustomDataUpdateModel custom_data_update: The replacement custom data entries
Returns

The updated full activity configuration

@abstractmethod
def delete_activity_config(self, key: str) -> inmotion.models.ActivityConfigDeleteResponseModel:
1224    @abstractmethod
1225    def delete_activity_config(self, key: str) -> ActivityConfigDeleteResponseModel:
1226        """ Delete the entire activity configuration for an activity
1227
1228        :param str key: The unique key of the activity
1229        :return: The result of the delete operation
1230        :rtype: ActivityConfigDeleteResponseModel
1231        """
1232        pass

Delete the entire activity configuration for an activity

Parameters
  • str key: The unique key of the activity
Returns

The result of the delete operation

@abstractmethod
def detect_bad_periods( self, key: str, request: inmotion.models.ActivityConfigBadPeriodDetectRequestModel) -> inmotion.models.ActivityConfigBadPeriodDetectResultModel:
1234    @abstractmethod
1235    def detect_bad_periods(self, key: str, request: ActivityConfigBadPeriodDetectRequestModel) -> ActivityConfigBadPeriodDetectResultModel:
1236        """ Run GPS-spike analysis on a track activity's raw data to detect candidate bad-time periods
1237
1238        :param str key: The unique key of the (track) activity
1239        :param ActivityConfigBadPeriodDetectRequestModel request: An optional time window to constrain detection
1240        :return: The detected candidate bad periods
1241        :rtype: ActivityConfigBadPeriodDetectResultModel
1242        """
1243        pass

Run GPS-spike analysis on a track activity's raw data to detect candidate bad-time periods

Parameters
  • str key: The unique key of the (track) activity
  • ActivityConfigBadPeriodDetectRequestModel request: An optional time window to constrain detection
Returns

The detected candidate bad periods

@abstractmethod
def merge_bad_periods( self, key: str, request: inmotion.models.ActivityConfigBadPeriodMergeRequestModel) -> inmotion.models.ActivityConfigBadPeriodMergeResultModel:
1245    @abstractmethod
1246    def merge_bad_periods(self, key: str, request: ActivityConfigBadPeriodMergeRequestModel) -> ActivityConfigBadPeriodMergeResultModel:
1247        """ Merge bad periods into the Quality Control section of an activity's configuration
1248
1249        :param str key: The unique key of the activity
1250        :param ActivityConfigBadPeriodMergeRequestModel request: The periods to merge, and whether this is a dry run
1251        :return: The resulting QC config YAML and merge metadata
1252        :rtype: ActivityConfigBadPeriodMergeResultModel
1253        """
1254        pass

Merge bad periods into the Quality Control section of an activity's configuration

Parameters
  • str key: The unique key of the activity
  • ActivityConfigBadPeriodMergeRequestModel request: The periods to merge, and whether this is a dry run
Returns

The resulting QC config YAML and merge metadata

@abstractmethod
def generate_qc_regions( self, key: str, request: inmotion.models.ActivityConfigQCRegionGenerateRequestModel) -> inmotion.models.ActivityConfigQCRegionGenerateResultModel:
1256    @abstractmethod
1257    def generate_qc_regions(self, key: str, request: ActivityConfigQCRegionGenerateRequestModel) -> ActivityConfigQCRegionGenerateResultModel:
1258        """ Analyze an activity's raw data and generate candidate, labelled QC regions
1259
1260        :param str key: The unique key of the activity
1261        :param ActivityConfigQCRegionGenerateRequestModel request: An optional time window to constrain detection
1262        :return: The generated candidate QC regions
1263        :rtype: ActivityConfigQCRegionGenerateResultModel
1264        """
1265        pass

Analyze an activity's raw data and generate candidate, labelled QC regions

Parameters
  • str key: The unique key of the activity
  • ActivityConfigQCRegionGenerateRequestModel request: An optional time window to constrain detection
Returns

The generated candidate QC regions

class InMotionApiKeys(abc.ABC):
1325class InMotionApiKeys(ABC):
1326    @abstractmethod
1327    def find_api_keys(self, account_key: str) -> list[AccountAPIKeyModel]:
1328        """ Retrieve the API keys associated with an account
1329
1330        :param str account_key: The unique key of the account
1331        :return: The account's API keys
1332        :rtype: list[AccountAPIKeyModel]
1333        """
1334        pass
1335
1336    @abstractmethod
1337    def create_api_key(self, account_key: str, creator: AccountAPIKeyCreatorModel) -> AccountAPIKeyModel:
1338        """ Create a new API key for an account
1339
1340        :param str account_key: The unique key of the account
1341        :param AccountAPIKeyCreatorModel creator: The definition of the API key to create
1342        :return: The created API key
1343        :rtype: AccountAPIKeyModel
1344        """
1345        pass
1346
1347    @abstractmethod
1348    def update_api_key(self, account_key: str, api_key: str, updator: AccountAPIKeyUpdatorModel) -> AccountAPIKeyModel:
1349        """ Update an existing API key
1350
1351        :param str account_key: The unique key of the account
1352        :param str api_key: The API key to update
1353        :param AccountAPIKeyUpdatorModel updator: The updated fields for the API key
1354        :return: The updated API key
1355        :rtype: AccountAPIKeyModel
1356        """
1357        pass
1358
1359    @abstractmethod
1360    def delete_api_key(self, account_key: str, api_key: str) -> AccountAPIKeyResponseModel:
1361        """ Delete an API key from an account
1362
1363        :param str account_key: The unique key of the account
1364        :param str api_key: The API key to delete
1365        :return: The result of the delete operation
1366        :rtype: AccountAPIKeyResponseModel
1367        """
1368        pass
1369
1370    @abstractmethod
1371    def find_api_key(self, account_key: str, api_key: str) -> AccountAPIKeyModel:
1372        """ Find a specific API key belonging to an account
1373
1374        :param str account_key: The unique key of the account
1375        :param str api_key: The API key to retrieve
1376        :return: The API key
1377        :rtype: AccountAPIKeyModel
1378        """
1379        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def find_api_keys(self, account_key: str) -> list[inmotion.models.AccountAPIKeyModel]:
1326    @abstractmethod
1327    def find_api_keys(self, account_key: str) -> list[AccountAPIKeyModel]:
1328        """ Retrieve the API keys associated with an account
1329
1330        :param str account_key: The unique key of the account
1331        :return: The account's API keys
1332        :rtype: list[AccountAPIKeyModel]
1333        """
1334        pass

Retrieve the API keys associated with an account

Parameters
  • str account_key: The unique key of the account
Returns

The account's API keys

@abstractmethod
def create_api_key( self, account_key: str, creator: inmotion.models.AccountAPIKeyCreatorModel) -> inmotion.models.AccountAPIKeyModel:
1336    @abstractmethod
1337    def create_api_key(self, account_key: str, creator: AccountAPIKeyCreatorModel) -> AccountAPIKeyModel:
1338        """ Create a new API key for an account
1339
1340        :param str account_key: The unique key of the account
1341        :param AccountAPIKeyCreatorModel creator: The definition of the API key to create
1342        :return: The created API key
1343        :rtype: AccountAPIKeyModel
1344        """
1345        pass

Create a new API key for an account

Parameters
  • str account_key: The unique key of the account
  • AccountAPIKeyCreatorModel creator: The definition of the API key to create
Returns

The created API key

@abstractmethod
def update_api_key( self, account_key: str, api_key: str, updator: inmotion.models.AccountAPIKeyUpdatorModel) -> inmotion.models.AccountAPIKeyModel:
1347    @abstractmethod
1348    def update_api_key(self, account_key: str, api_key: str, updator: AccountAPIKeyUpdatorModel) -> AccountAPIKeyModel:
1349        """ Update an existing API key
1350
1351        :param str account_key: The unique key of the account
1352        :param str api_key: The API key to update
1353        :param AccountAPIKeyUpdatorModel updator: The updated fields for the API key
1354        :return: The updated API key
1355        :rtype: AccountAPIKeyModel
1356        """
1357        pass

Update an existing API key

Parameters
  • str account_key: The unique key of the account
  • str api_key: The API key to update
  • AccountAPIKeyUpdatorModel updator: The updated fields for the API key
Returns

The updated API key

@abstractmethod
def delete_api_key( self, account_key: str, api_key: str) -> inmotion.models.AccountAPIKeyResponseModel:
1359    @abstractmethod
1360    def delete_api_key(self, account_key: str, api_key: str) -> AccountAPIKeyResponseModel:
1361        """ Delete an API key from an account
1362
1363        :param str account_key: The unique key of the account
1364        :param str api_key: The API key to delete
1365        :return: The result of the delete operation
1366        :rtype: AccountAPIKeyResponseModel
1367        """
1368        pass

Delete an API key from an account

Parameters
  • str account_key: The unique key of the account
  • str api_key: The API key to delete
Returns

The result of the delete operation

@abstractmethod
def find_api_key( self, account_key: str, api_key: str) -> inmotion.models.AccountAPIKeyModel:
1370    @abstractmethod
1371    def find_api_key(self, account_key: str, api_key: str) -> AccountAPIKeyModel:
1372        """ Find a specific API key belonging to an account
1373
1374        :param str account_key: The unique key of the account
1375        :param str api_key: The API key to retrieve
1376        :return: The API key
1377        :rtype: AccountAPIKeyModel
1378        """
1379        pass

Find a specific API key belonging to an account

Parameters
  • str account_key: The unique key of the account
  • str api_key: The API key to retrieve
Returns

The API key

class InMotionAudit(abc.ABC):
2304class InMotionAudit(ABC):
2305    """ Write-only access to the external audit log: third-party integrations record their own
2306    audit trail entries here, distinct from inMotion's internal account/user audit trail. """
2307
2308    @abstractmethod
2309    def create_audit_batch(self, batch: ExternalAuditBatchModel) -> list[ActivityBatchResultModel]:
2310        """ Write a batch of external audit records (max 100 per batch)
2311
2312        :param ExternalAuditBatchModel batch: The records to write, optionally scoped to an account
2313        :return: One result per submitted record, in the same order, each carrying its own status
2314        :rtype: list[ActivityBatchResultModel]
2315        """
2316        pass

Write-only access to the external audit log: third-party integrations record their own audit trail entries here, distinct from inMotion's internal account/user audit trail.

@abstractmethod
def create_audit_batch( self, batch: inmotion.models.ExternalAuditBatchModel) -> list[inmotion.models.ActivityBatchResultModel]:
2308    @abstractmethod
2309    def create_audit_batch(self, batch: ExternalAuditBatchModel) -> list[ActivityBatchResultModel]:
2310        """ Write a batch of external audit records (max 100 per batch)
2311
2312        :param ExternalAuditBatchModel batch: The records to write, optionally scoped to an account
2313        :return: One result per submitted record, in the same order, each carrying its own status
2314        :rtype: list[ActivityBatchResultModel]
2315        """
2316        pass

Write a batch of external audit records (max 100 per batch)

Parameters
  • ExternalAuditBatchModel batch: The records to write, optionally scoped to an account
Returns

One result per submitted record, in the same order, each carrying its own status

class InMotionDataStream(abc.ABC):
2530class InMotionDataStream(ABC):
2531    """ Data stream management: the data stream entity itself, its hyperslab (array/gridded) data
2532    channels, and its blob (byte-oriented) data channels.
2533
2534    A handful of methods here return a raw ``dict`` rather than a typed model. This isn't a
2535    shortcut - those specific endpoints (hyperslab channel management, and hyperslab invariant/
2536    record data read and write) have no fixed JSON schema on the server: their shape is derived
2537    dynamically per data-channel definition (variable names/types), not declared as a dataclass
2538    anywhere in the server's own model layer. Modeling them as a fixed dataclass here would be
2539    guessing a schema the server itself doesn't have.
2540    """
2541
2542    @abstractmethod
2543    def create_data_stream(self, creator: DataStreamCreatorModel) -> DataStreamDetailsModel:
2544        """ Create a new data stream
2545
2546        :param DataStreamCreatorModel creator: The definition of the data stream to create
2547        :return: The created data stream's details
2548        :rtype: DataStreamDetailsModel
2549        """
2550        pass
2551
2552    @abstractmethod
2553    def update_data_stream(self, key: str, creator: DataStreamCreatorModel) -> DataStreamDetailsModel:
2554        """ Update an existing data stream
2555
2556        :param str key: The unique key of the data stream to update
2557        :param DataStreamCreatorModel creator: The updated definition of the data stream
2558        :return: The updated data stream's details
2559        :rtype: DataStreamDetailsModel
2560        """
2561        pass
2562
2563    @abstractmethod
2564    def find_data_stream(self, key: str) -> DataStreamDetailsModel:
2565        """ Find a data stream by its unique key
2566
2567        :param str key: The unique key of the data stream
2568        :return: The data stream's details
2569        :rtype: DataStreamDetailsModel
2570        """
2571        pass
2572
2573    @abstractmethod
2574    def delete_data_stream(self, key: str) -> dict:
2575        """ Delete a data stream
2576
2577        :param str key: The unique key of the data stream to delete
2578        :return: A raw dict with a 'message' key confirming deletion
2579        :rtype: dict
2580        """
2581        pass
2582
2583    @abstractmethod
2584    def unlock_data_stream(self, key: str) -> dict:
2585        """ Unlock a data stream so that it can be modified or updated
2586
2587        :param str key: The unique key of the data stream to unlock
2588        :return: A raw dict with a 'message' key confirming the unlock
2589        :rtype: dict
2590        """
2591        pass
2592
2593    @abstractmethod
2594    def find_data_streams(self, data_stream_filter: DataStreamFilterModel) -> list[DataStreamSummaryModel]:
2595        """ Find data streams matching a filter
2596
2597        :param DataStreamFilterModel data_stream_filter: The filter to apply to the search
2598        :return: Summaries of the matching data streams
2599        :rtype: list[DataStreamSummaryModel]
2600        """
2601        pass
2602
2603    @abstractmethod
2604    def find_data_streams_by_name(self, account: str, name_pattern: str) -> list[DataStreamSummaryModel]:
2605        """ Find data streams for an account matching a (partial) name
2606
2607        :param str account: The unique key of the account
2608        :param str name_pattern: A partial name to match data streams against
2609        :return: Summaries of the matching data streams
2610        :rtype: list[DataStreamSummaryModel]
2611        """
2612        pass
2613
2614    @abstractmethod
2615    def create_hyperslab_channel(self, key: str, creator: DataChannelCreatorModel) -> dict:
2616        """ Create a hyperslab (array/gridded) data channel on a data stream
2617
2618        :param str key: The unique key of the data stream
2619        :param DataChannelCreatorModel creator: The definition of the data channel to create
2620        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2621        :rtype: dict
2622        """
2623        pass
2624
2625    @abstractmethod
2626    def update_hyperslab_channel(self, key: str, channel_code: str, creator: DataChannelCreatorModel) -> dict:
2627        """ Update an existing hyperslab data channel
2628
2629        :param str key: The unique key of the data stream
2630        :param str channel_code: The code identifying the channel type to update
2631        :param DataChannelCreatorModel creator: The updated definition of the data channel
2632        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2633        :rtype: dict
2634        """
2635        pass
2636
2637    @abstractmethod
2638    def delete_hyperslab_channel(self, key: str, channel_code: str) -> dict:
2639        """ Delete a hyperslab data channel
2640
2641        :param str key: The unique key of the data stream
2642        :param str channel_code: The code identifying the channel type to delete
2643        :return: A raw dict with 'dsKey', 'channelType', and 'status' keys
2644        :rtype: dict
2645        """
2646        pass
2647
2648    @abstractmethod
2649    def find_invariant_hyperslab_data(self, key: str, channel_code: str) -> dict:
2650        """ Retrieve the invariant (static, non-time-varying) data for a hyperslab channel
2651
2652        :param str key: The unique key of the data stream
2653        :param str channel_code: The code identifying the channel type
2654        :return: A raw dict of the invariant data, shaped per the channel's own variable definitions
2655        :rtype: dict
2656        """
2657        pass
2658
2659    @abstractmethod
2660    def update_invariant_hyperslab_data(self, key: str, channel_code: str, data: dict) -> dict:
2661        """ Update the invariant (static, non-time-varying) data for a hyperslab channel
2662
2663        :param str key: The unique key of the data stream
2664        :param str channel_code: The code identifying the channel type
2665        :param dict data: The invariant data, shaped per the channel's own variable definitions
2666        :return: A raw dict with a 'message' key confirming the update
2667        :rtype: dict
2668        """
2669        pass
2670
2671    @abstractmethod
2672    def find_hyperslab_record_data(self, key: str, channel_code: str, start: datetime, end: datetime) -> dict:
2673        """ Retrieve hyperslab record (time-varying) data within a time range
2674
2675        :param str key: The unique key of the data stream
2676        :param str channel_code: The code identifying the channel type
2677        :param datetime start: The start of the time range (inclusive)
2678        :param datetime end: The end of the time range (inclusive)
2679        :return: A raw dict of the record data, shaped per the channel's own variable definitions
2680        :rtype: dict
2681        """
2682        pass
2683
2684    @abstractmethod
2685    def retrieve_statistics(self, key: str, channel_code: str, start: datetime, end: datetime,
2686                            max_points: Optional[int] = None, bucket_ms: Optional[int] = None,
2687                            unit_system: Optional[str] = None) -> StatisticsModel:
2688        """ Retrieve roll-up statistics (per-bucket count, mean, spread) for a window of a channel
2689
2690        :param str key: The unique key of the data stream
2691        :param str channel_code: The code of the source channel (not a roll-up channel)
2692        :param datetime start: The start of the window (naive values are taken as UTC)
2693        :param datetime end: The end of the window
2694        :param int max_points: The most buckets to return; coarser buckets are chosen to fit
2695        :param int bucket_ms: A bucket length to ask for, instead of letting the server choose
2696        :param str unit_system: The unit system for the values (default: the user's preferred system)
2697        :return: The bucket times and per-variable columns (n, mean, min, max, ...); `available`
2698                 is false when no roll-up covers the request, in which case read the raw records instead
2699        :rtype: StatisticsModel
2700        """
2701        pass
2702
2703    @abstractmethod
2704    def update_hyperslab_record_data(self, key: str, channel_code: str, data: dict) -> dict:
2705        """ Update hyperslab record (time-varying) data
2706
2707        :param str key: The unique key of the data stream
2708        :param str channel_code: The code identifying the channel type
2709        :param dict data: The record data, shaped per the channel's own variable definitions
2710        :return: A raw dict with a 'message' key confirming the update
2711        :rtype: dict
2712        """
2713        pass
2714
2715    @abstractmethod
2716    def create_blob_channel(self, key: str, creator: DataChannelCreatorModel) -> dict:
2717        """ Create a blob (byte-oriented) data channel on a data stream
2718
2719        :param str key: The unique key of the data stream
2720        :param DataChannelCreatorModel creator: The definition of the data channel to create
2721        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2722        :rtype: dict
2723        """
2724        pass
2725
2726    @abstractmethod
2727    def update_blob_channel(self, key: str, channel_code: str, creator: DataChannelCreatorModel) -> dict:
2728        """ Update an existing blob data channel
2729
2730        :param str key: The unique key of the data stream
2731        :param str channel_code: The code identifying the channel type to update
2732        :param DataChannelCreatorModel creator: The updated definition of the data channel
2733        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2734        :rtype: dict
2735        """
2736        pass
2737
2738    @abstractmethod
2739    def delete_blob_channel(self, key: str, channel_code: str) -> dict:
2740        """ Delete a blob data channel
2741
2742        :param str key: The unique key of the data stream
2743        :param str channel_code: The code identifying the channel type to delete
2744        :return: A raw dict with 'dsKey', 'channelType', and 'status' keys
2745        :rtype: dict
2746        """
2747        pass
2748
2749    @abstractmethod
2750    def find_invariant_blob_data(self, key: str, channel_code: str, profile: str) -> DataStreamInvariantBlobMetadataModel:
2751        """ Retrieve the metadata for the invariant (static) blob data of a channel/profile
2752
2753        :param str key: The unique key of the data stream
2754        :param str channel_code: The code identifying the channel type
2755        :param str profile: The storage profile to retrieve
2756        :return: The invariant blob's metadata
2757        :rtype: DataStreamInvariantBlobMetadataModel
2758        """
2759        pass
2760
2761    @abstractmethod
2762    def update_invariant_blob_data(self, key: str, channel_code: str, profile: str, data: bytes) -> DataStreamInvariantBlobMetadataModel:
2763        """ Update the invariant (static) blob data of a channel/profile
2764
2765        :param str key: The unique key of the data stream
2766        :param str channel_code: The code identifying the channel type
2767        :param str profile: The storage profile to update
2768        :param bytes data: The raw bytes to store
2769        :return: The updated invariant blob's metadata
2770        :rtype: DataStreamInvariantBlobMetadataModel
2771        """
2772        pass
2773
2774    @abstractmethod
2775    def register_invariant_blob_data(self, key: str, channel_code: str, profile: str, data_uuid: str) -> DataStreamInvariantBlobMetadataModel:
2776        """ Register already-uploaded data as the invariant (static) blob of a channel/profile
2777
2778        :param str key: The unique key of the data stream
2779        :param str channel_code: The code identifying the channel type
2780        :param str profile: The storage profile to update
2781        :param str data_uuid: The identifier of the stored data to register
2782        :return: The registered invariant blob's metadata
2783        :rtype: DataStreamInvariantBlobMetadataModel
2784        """
2785        pass
2786
2787    @abstractmethod
2788    def find_blob_record_data(self, key: str, channel_code: str, start: datetime, end: datetime, profile: str) -> dict[str, DataStreamRecordsBlobMetadataModel]:
2789        """ Retrieve the metadata for blob record data within a time range
2790
2791        :param str key: The unique key of the data stream
2792        :param str channel_code: The code identifying the channel type
2793        :param datetime start: The start of the time range (inclusive)
2794        :param datetime end: The end of the time range (inclusive)
2795        :param str profile: The storage profile to retrieve
2796        :return: A map of interval identifier to the matching blob record's metadata
2797        :rtype: dict[str, DataStreamRecordsBlobMetadataModel]
2798        """
2799        pass
2800
2801    @abstractmethod
2802    def find_latest_blob_record_data(self, key: str, channel_code: str, profile: str) -> DataStreamRecordsBlobMetadataModel:
2803        """ Retrieve the metadata for the most recent blob record data of a channel/profile
2804
2805        :param str key: The unique key of the data stream
2806        :param str channel_code: The code identifying the channel type
2807        :param str profile: The storage profile to retrieve
2808        :return: The latest blob record's metadata
2809        :rtype: DataStreamRecordsBlobMetadataModel
2810        """
2811        pass
2812
2813    @abstractmethod
2814    def update_blob_record_data(self, key: str, channel_code: str, start: datetime, end: datetime, profile: str, data: bytes) -> DataStreamRecordsBlobMetadataModel:
2815        """ Update blob record data within a time range
2816
2817        :param str key: The unique key of the data stream
2818        :param str channel_code: The code identifying the channel type
2819        :param datetime start: The start of the time range (inclusive)
2820        :param datetime end: The end of the time range (inclusive)
2821        :param str profile: The storage profile to update
2822        :param bytes data: The raw bytes to store
2823        :return: The updated blob record's metadata
2824        :rtype: DataStreamRecordsBlobMetadataModel
2825        """
2826        pass
2827
2828    @abstractmethod
2829    def open_blob_stream(self, key: str, blob_key: str) -> bytes:
2830        """ Open and read a raw blob's byte stream
2831
2832        :param str key: The unique key of the data stream
2833        :param str blob_key: The unique key of the blob to read
2834        :return: The raw blob content
2835        :rtype: bytes
2836        """
2837        pass
2838
2839    @abstractmethod
2840    def find_blobs(self, data_stream_filter: DataStreamFilterModel) -> list[DataStreamBlobSummaryModel]:
2841        """ Find data stream blobs matching a filter
2842
2843        :param DataStreamFilterModel data_stream_filter: The filter to apply to the search
2844        :return: Summaries of the matching data stream blobs
2845        :rtype: list[DataStreamBlobSummaryModel]
2846        """
2847        pass

Data stream management: the data stream entity itself, its hyperslab (array/gridded) data channels, and its blob (byte-oriented) data channels.

A handful of methods here return a raw dict rather than a typed model. This isn't a shortcut - those specific endpoints (hyperslab channel management, and hyperslab invariant/ record data read and write) have no fixed JSON schema on the server: their shape is derived dynamically per data-channel definition (variable names/types), not declared as a dataclass anywhere in the server's own model layer. Modeling them as a fixed dataclass here would be guessing a schema the server itself doesn't have.

@abstractmethod
def create_data_stream( self, creator: inmotion.models.DataStreamCreatorModel) -> inmotion.models.DataStreamDetailsModel:
2542    @abstractmethod
2543    def create_data_stream(self, creator: DataStreamCreatorModel) -> DataStreamDetailsModel:
2544        """ Create a new data stream
2545
2546        :param DataStreamCreatorModel creator: The definition of the data stream to create
2547        :return: The created data stream's details
2548        :rtype: DataStreamDetailsModel
2549        """
2550        pass

Create a new data stream

Parameters
  • DataStreamCreatorModel creator: The definition of the data stream to create
Returns

The created data stream's details

@abstractmethod
def update_data_stream( self, key: str, creator: inmotion.models.DataStreamCreatorModel) -> inmotion.models.DataStreamDetailsModel:
2552    @abstractmethod
2553    def update_data_stream(self, key: str, creator: DataStreamCreatorModel) -> DataStreamDetailsModel:
2554        """ Update an existing data stream
2555
2556        :param str key: The unique key of the data stream to update
2557        :param DataStreamCreatorModel creator: The updated definition of the data stream
2558        :return: The updated data stream's details
2559        :rtype: DataStreamDetailsModel
2560        """
2561        pass

Update an existing data stream

Parameters
  • str key: The unique key of the data stream to update
  • DataStreamCreatorModel creator: The updated definition of the data stream
Returns

The updated data stream's details

@abstractmethod
def find_data_stream(self, key: str) -> inmotion.models.DataStreamDetailsModel:
2563    @abstractmethod
2564    def find_data_stream(self, key: str) -> DataStreamDetailsModel:
2565        """ Find a data stream by its unique key
2566
2567        :param str key: The unique key of the data stream
2568        :return: The data stream's details
2569        :rtype: DataStreamDetailsModel
2570        """
2571        pass

Find a data stream by its unique key

Parameters
  • str key: The unique key of the data stream
Returns

The data stream's details

@abstractmethod
def delete_data_stream(self, key: str) -> dict:
2573    @abstractmethod
2574    def delete_data_stream(self, key: str) -> dict:
2575        """ Delete a data stream
2576
2577        :param str key: The unique key of the data stream to delete
2578        :return: A raw dict with a 'message' key confirming deletion
2579        :rtype: dict
2580        """
2581        pass

Delete a data stream

Parameters
  • str key: The unique key of the data stream to delete
Returns

A raw dict with a 'message' key confirming deletion

@abstractmethod
def unlock_data_stream(self, key: str) -> dict:
2583    @abstractmethod
2584    def unlock_data_stream(self, key: str) -> dict:
2585        """ Unlock a data stream so that it can be modified or updated
2586
2587        :param str key: The unique key of the data stream to unlock
2588        :return: A raw dict with a 'message' key confirming the unlock
2589        :rtype: dict
2590        """
2591        pass

Unlock a data stream so that it can be modified or updated

Parameters
  • str key: The unique key of the data stream to unlock
Returns

A raw dict with a 'message' key confirming the unlock

@abstractmethod
def find_data_streams( self, data_stream_filter: inmotion.models.DataStreamFilterModel) -> list[inmotion.models.DataStreamSummaryModel]:
2593    @abstractmethod
2594    def find_data_streams(self, data_stream_filter: DataStreamFilterModel) -> list[DataStreamSummaryModel]:
2595        """ Find data streams matching a filter
2596
2597        :param DataStreamFilterModel data_stream_filter: The filter to apply to the search
2598        :return: Summaries of the matching data streams
2599        :rtype: list[DataStreamSummaryModel]
2600        """
2601        pass

Find data streams matching a filter

Parameters
  • DataStreamFilterModel data_stream_filter: The filter to apply to the search
Returns

Summaries of the matching data streams

@abstractmethod
def find_data_streams_by_name( self, account: str, name_pattern: str) -> list[inmotion.models.DataStreamSummaryModel]:
2603    @abstractmethod
2604    def find_data_streams_by_name(self, account: str, name_pattern: str) -> list[DataStreamSummaryModel]:
2605        """ Find data streams for an account matching a (partial) name
2606
2607        :param str account: The unique key of the account
2608        :param str name_pattern: A partial name to match data streams against
2609        :return: Summaries of the matching data streams
2610        :rtype: list[DataStreamSummaryModel]
2611        """
2612        pass

Find data streams for an account matching a (partial) name

Parameters
  • str account: The unique key of the account
  • str name_pattern: A partial name to match data streams against
Returns

Summaries of the matching data streams

@abstractmethod
def create_hyperslab_channel(self, key: str, creator: inmotion.models.DataChannelCreatorModel) -> dict:
2614    @abstractmethod
2615    def create_hyperslab_channel(self, key: str, creator: DataChannelCreatorModel) -> dict:
2616        """ Create a hyperslab (array/gridded) data channel on a data stream
2617
2618        :param str key: The unique key of the data stream
2619        :param DataChannelCreatorModel creator: The definition of the data channel to create
2620        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2621        :rtype: dict
2622        """
2623        pass

Create a hyperslab (array/gridded) data channel on a data stream

Parameters
  • str key: The unique key of the data stream
  • DataChannelCreatorModel creator: The definition of the data channel to create
Returns

A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys

@abstractmethod
def update_hyperslab_channel( self, key: str, channel_code: str, creator: inmotion.models.DataChannelCreatorModel) -> dict:
2625    @abstractmethod
2626    def update_hyperslab_channel(self, key: str, channel_code: str, creator: DataChannelCreatorModel) -> dict:
2627        """ Update an existing hyperslab data channel
2628
2629        :param str key: The unique key of the data stream
2630        :param str channel_code: The code identifying the channel type to update
2631        :param DataChannelCreatorModel creator: The updated definition of the data channel
2632        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2633        :rtype: dict
2634        """
2635        pass

Update an existing hyperslab data channel

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type to update
  • DataChannelCreatorModel creator: The updated definition of the data channel
Returns

A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys

@abstractmethod
def delete_hyperslab_channel(self, key: str, channel_code: str) -> dict:
2637    @abstractmethod
2638    def delete_hyperslab_channel(self, key: str, channel_code: str) -> dict:
2639        """ Delete a hyperslab data channel
2640
2641        :param str key: The unique key of the data stream
2642        :param str channel_code: The code identifying the channel type to delete
2643        :return: A raw dict with 'dsKey', 'channelType', and 'status' keys
2644        :rtype: dict
2645        """
2646        pass

Delete a hyperslab data channel

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type to delete
Returns

A raw dict with 'dsKey', 'channelType', and 'status' keys

@abstractmethod
def find_invariant_hyperslab_data(self, key: str, channel_code: str) -> dict:
2648    @abstractmethod
2649    def find_invariant_hyperslab_data(self, key: str, channel_code: str) -> dict:
2650        """ Retrieve the invariant (static, non-time-varying) data for a hyperslab channel
2651
2652        :param str key: The unique key of the data stream
2653        :param str channel_code: The code identifying the channel type
2654        :return: A raw dict of the invariant data, shaped per the channel's own variable definitions
2655        :rtype: dict
2656        """
2657        pass

Retrieve the invariant (static, non-time-varying) data for a hyperslab channel

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
Returns

A raw dict of the invariant data, shaped per the channel's own variable definitions

@abstractmethod
def update_invariant_hyperslab_data(self, key: str, channel_code: str, data: dict) -> dict:
2659    @abstractmethod
2660    def update_invariant_hyperslab_data(self, key: str, channel_code: str, data: dict) -> dict:
2661        """ Update the invariant (static, non-time-varying) data for a hyperslab channel
2662
2663        :param str key: The unique key of the data stream
2664        :param str channel_code: The code identifying the channel type
2665        :param dict data: The invariant data, shaped per the channel's own variable definitions
2666        :return: A raw dict with a 'message' key confirming the update
2667        :rtype: dict
2668        """
2669        pass

Update the invariant (static, non-time-varying) data for a hyperslab channel

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • dict data: The invariant data, shaped per the channel's own variable definitions
Returns

A raw dict with a 'message' key confirming the update

@abstractmethod
def find_hyperslab_record_data( self, key: str, channel_code: str, start: datetime.datetime, end: datetime.datetime) -> dict:
2671    @abstractmethod
2672    def find_hyperslab_record_data(self, key: str, channel_code: str, start: datetime, end: datetime) -> dict:
2673        """ Retrieve hyperslab record (time-varying) data within a time range
2674
2675        :param str key: The unique key of the data stream
2676        :param str channel_code: The code identifying the channel type
2677        :param datetime start: The start of the time range (inclusive)
2678        :param datetime end: The end of the time range (inclusive)
2679        :return: A raw dict of the record data, shaped per the channel's own variable definitions
2680        :rtype: dict
2681        """
2682        pass

Retrieve hyperslab record (time-varying) data within a time range

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • datetime start: The start of the time range (inclusive)
  • datetime end: The end of the time range (inclusive)
Returns

A raw dict of the record data, shaped per the channel's own variable definitions

@abstractmethod
def retrieve_statistics( self, key: str, channel_code: str, start: datetime.datetime, end: datetime.datetime, max_points: Optional[int] = None, bucket_ms: Optional[int] = None, unit_system: Optional[str] = None) -> inmotion.models.StatisticsModel:
2684    @abstractmethod
2685    def retrieve_statistics(self, key: str, channel_code: str, start: datetime, end: datetime,
2686                            max_points: Optional[int] = None, bucket_ms: Optional[int] = None,
2687                            unit_system: Optional[str] = None) -> StatisticsModel:
2688        """ Retrieve roll-up statistics (per-bucket count, mean, spread) for a window of a channel
2689
2690        :param str key: The unique key of the data stream
2691        :param str channel_code: The code of the source channel (not a roll-up channel)
2692        :param datetime start: The start of the window (naive values are taken as UTC)
2693        :param datetime end: The end of the window
2694        :param int max_points: The most buckets to return; coarser buckets are chosen to fit
2695        :param int bucket_ms: A bucket length to ask for, instead of letting the server choose
2696        :param str unit_system: The unit system for the values (default: the user's preferred system)
2697        :return: The bucket times and per-variable columns (n, mean, min, max, ...); `available`
2698                 is false when no roll-up covers the request, in which case read the raw records instead
2699        :rtype: StatisticsModel
2700        """
2701        pass

Retrieve roll-up statistics (per-bucket count, mean, spread) for a window of a channel

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code of the source channel (not a roll-up channel)
  • datetime start: The start of the window (naive values are taken as UTC)
  • datetime end: The end of the window
  • int max_points: The most buckets to return; coarser buckets are chosen to fit
  • int bucket_ms: A bucket length to ask for, instead of letting the server choose
  • str unit_system: The unit system for the values (default: the user's preferred system)
Returns

The bucket times and per-variable columns (n, mean, min, max, ...); available is false when no roll-up covers the request, in which case read the raw records instead

@abstractmethod
def update_hyperslab_record_data(self, key: str, channel_code: str, data: dict) -> dict:
2703    @abstractmethod
2704    def update_hyperslab_record_data(self, key: str, channel_code: str, data: dict) -> dict:
2705        """ Update hyperslab record (time-varying) data
2706
2707        :param str key: The unique key of the data stream
2708        :param str channel_code: The code identifying the channel type
2709        :param dict data: The record data, shaped per the channel's own variable definitions
2710        :return: A raw dict with a 'message' key confirming the update
2711        :rtype: dict
2712        """
2713        pass

Update hyperslab record (time-varying) data

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • dict data: The record data, shaped per the channel's own variable definitions
Returns

A raw dict with a 'message' key confirming the update

@abstractmethod
def create_blob_channel(self, key: str, creator: inmotion.models.DataChannelCreatorModel) -> dict:
2715    @abstractmethod
2716    def create_blob_channel(self, key: str, creator: DataChannelCreatorModel) -> dict:
2717        """ Create a blob (byte-oriented) data channel on a data stream
2718
2719        :param str key: The unique key of the data stream
2720        :param DataChannelCreatorModel creator: The definition of the data channel to create
2721        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2722        :rtype: dict
2723        """
2724        pass

Create a blob (byte-oriented) data channel on a data stream

Parameters
  • str key: The unique key of the data stream
  • DataChannelCreatorModel creator: The definition of the data channel to create
Returns

A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys

@abstractmethod
def update_blob_channel( self, key: str, channel_code: str, creator: inmotion.models.DataChannelCreatorModel) -> dict:
2726    @abstractmethod
2727    def update_blob_channel(self, key: str, channel_code: str, creator: DataChannelCreatorModel) -> dict:
2728        """ Update an existing blob data channel
2729
2730        :param str key: The unique key of the data stream
2731        :param str channel_code: The code identifying the channel type to update
2732        :param DataChannelCreatorModel creator: The updated definition of the data channel
2733        :return: A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys
2734        :rtype: dict
2735        """
2736        pass

Update an existing blob data channel

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type to update
  • DataChannelCreatorModel creator: The updated definition of the data channel
Returns

A raw dict with 'dsKey', 'channelType', 'status', and 'dataChannel' keys

@abstractmethod
def delete_blob_channel(self, key: str, channel_code: str) -> dict:
2738    @abstractmethod
2739    def delete_blob_channel(self, key: str, channel_code: str) -> dict:
2740        """ Delete a blob data channel
2741
2742        :param str key: The unique key of the data stream
2743        :param str channel_code: The code identifying the channel type to delete
2744        :return: A raw dict with 'dsKey', 'channelType', and 'status' keys
2745        :rtype: dict
2746        """
2747        pass

Delete a blob data channel

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type to delete
Returns

A raw dict with 'dsKey', 'channelType', and 'status' keys

@abstractmethod
def find_invariant_blob_data( self, key: str, channel_code: str, profile: str) -> inmotion.models.DataStreamInvariantBlobMetadataModel:
2749    @abstractmethod
2750    def find_invariant_blob_data(self, key: str, channel_code: str, profile: str) -> DataStreamInvariantBlobMetadataModel:
2751        """ Retrieve the metadata for the invariant (static) blob data of a channel/profile
2752
2753        :param str key: The unique key of the data stream
2754        :param str channel_code: The code identifying the channel type
2755        :param str profile: The storage profile to retrieve
2756        :return: The invariant blob's metadata
2757        :rtype: DataStreamInvariantBlobMetadataModel
2758        """
2759        pass

Retrieve the metadata for the invariant (static) blob data of a channel/profile

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • str profile: The storage profile to retrieve
Returns

The invariant blob's metadata

@abstractmethod
def update_invariant_blob_data( self, key: str, channel_code: str, profile: str, data: bytes) -> inmotion.models.DataStreamInvariantBlobMetadataModel:
2761    @abstractmethod
2762    def update_invariant_blob_data(self, key: str, channel_code: str, profile: str, data: bytes) -> DataStreamInvariantBlobMetadataModel:
2763        """ Update the invariant (static) blob data of a channel/profile
2764
2765        :param str key: The unique key of the data stream
2766        :param str channel_code: The code identifying the channel type
2767        :param str profile: The storage profile to update
2768        :param bytes data: The raw bytes to store
2769        :return: The updated invariant blob's metadata
2770        :rtype: DataStreamInvariantBlobMetadataModel
2771        """
2772        pass

Update the invariant (static) blob data of a channel/profile

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • str profile: The storage profile to update
  • bytes data: The raw bytes to store
Returns

The updated invariant blob's metadata

@abstractmethod
def register_invariant_blob_data( self, key: str, channel_code: str, profile: str, data_uuid: str) -> inmotion.models.DataStreamInvariantBlobMetadataModel:
2774    @abstractmethod
2775    def register_invariant_blob_data(self, key: str, channel_code: str, profile: str, data_uuid: str) -> DataStreamInvariantBlobMetadataModel:
2776        """ Register already-uploaded data as the invariant (static) blob of a channel/profile
2777
2778        :param str key: The unique key of the data stream
2779        :param str channel_code: The code identifying the channel type
2780        :param str profile: The storage profile to update
2781        :param str data_uuid: The identifier of the stored data to register
2782        :return: The registered invariant blob's metadata
2783        :rtype: DataStreamInvariantBlobMetadataModel
2784        """
2785        pass

Register already-uploaded data as the invariant (static) blob of a channel/profile

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • str profile: The storage profile to update
  • str data_uuid: The identifier of the stored data to register
Returns

The registered invariant blob's metadata

@abstractmethod
def find_blob_record_data( self, key: str, channel_code: str, start: datetime.datetime, end: datetime.datetime, profile: str) -> dict[str, inmotion.models.DataStreamRecordsBlobMetadataModel]:
2787    @abstractmethod
2788    def find_blob_record_data(self, key: str, channel_code: str, start: datetime, end: datetime, profile: str) -> dict[str, DataStreamRecordsBlobMetadataModel]:
2789        """ Retrieve the metadata for blob record data within a time range
2790
2791        :param str key: The unique key of the data stream
2792        :param str channel_code: The code identifying the channel type
2793        :param datetime start: The start of the time range (inclusive)
2794        :param datetime end: The end of the time range (inclusive)
2795        :param str profile: The storage profile to retrieve
2796        :return: A map of interval identifier to the matching blob record's metadata
2797        :rtype: dict[str, DataStreamRecordsBlobMetadataModel]
2798        """
2799        pass

Retrieve the metadata for blob record data within a time range

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • datetime start: The start of the time range (inclusive)
  • datetime end: The end of the time range (inclusive)
  • str profile: The storage profile to retrieve
Returns

A map of interval identifier to the matching blob record's metadata

@abstractmethod
def find_latest_blob_record_data( self, key: str, channel_code: str, profile: str) -> inmotion.models.DataStreamRecordsBlobMetadataModel:
2801    @abstractmethod
2802    def find_latest_blob_record_data(self, key: str, channel_code: str, profile: str) -> DataStreamRecordsBlobMetadataModel:
2803        """ Retrieve the metadata for the most recent blob record data of a channel/profile
2804
2805        :param str key: The unique key of the data stream
2806        :param str channel_code: The code identifying the channel type
2807        :param str profile: The storage profile to retrieve
2808        :return: The latest blob record's metadata
2809        :rtype: DataStreamRecordsBlobMetadataModel
2810        """
2811        pass

Retrieve the metadata for the most recent blob record data of a channel/profile

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • str profile: The storage profile to retrieve
Returns

The latest blob record's metadata

@abstractmethod
def update_blob_record_data( self, key: str, channel_code: str, start: datetime.datetime, end: datetime.datetime, profile: str, data: bytes) -> inmotion.models.DataStreamRecordsBlobMetadataModel:
2813    @abstractmethod
2814    def update_blob_record_data(self, key: str, channel_code: str, start: datetime, end: datetime, profile: str, data: bytes) -> DataStreamRecordsBlobMetadataModel:
2815        """ Update blob record data within a time range
2816
2817        :param str key: The unique key of the data stream
2818        :param str channel_code: The code identifying the channel type
2819        :param datetime start: The start of the time range (inclusive)
2820        :param datetime end: The end of the time range (inclusive)
2821        :param str profile: The storage profile to update
2822        :param bytes data: The raw bytes to store
2823        :return: The updated blob record's metadata
2824        :rtype: DataStreamRecordsBlobMetadataModel
2825        """
2826        pass

Update blob record data within a time range

Parameters
  • str key: The unique key of the data stream
  • str channel_code: The code identifying the channel type
  • datetime start: The start of the time range (inclusive)
  • datetime end: The end of the time range (inclusive)
  • str profile: The storage profile to update
  • bytes data: The raw bytes to store
Returns

The updated blob record's metadata

@abstractmethod
def open_blob_stream(self, key: str, blob_key: str) -> bytes:
2828    @abstractmethod
2829    def open_blob_stream(self, key: str, blob_key: str) -> bytes:
2830        """ Open and read a raw blob's byte stream
2831
2832        :param str key: The unique key of the data stream
2833        :param str blob_key: The unique key of the blob to read
2834        :return: The raw blob content
2835        :rtype: bytes
2836        """
2837        pass

Open and read a raw blob's byte stream

Parameters
  • str key: The unique key of the data stream
  • str blob_key: The unique key of the blob to read
Returns

The raw blob content

@abstractmethod
def find_blobs( self, data_stream_filter: inmotion.models.DataStreamFilterModel) -> list[inmotion.models.DataStreamBlobSummaryModel]:
2839    @abstractmethod
2840    def find_blobs(self, data_stream_filter: DataStreamFilterModel) -> list[DataStreamBlobSummaryModel]:
2841        """ Find data stream blobs matching a filter
2842
2843        :param DataStreamFilterModel data_stream_filter: The filter to apply to the search
2844        :return: Summaries of the matching data stream blobs
2845        :rtype: list[DataStreamBlobSummaryModel]
2846        """
2847        pass

Find data stream blobs matching a filter

Parameters
  • DataStreamFilterModel data_stream_filter: The filter to apply to the search
Returns

Summaries of the matching data stream blobs

class InMotionDatasets(abc.ABC):
1960class InMotionDatasets(ABC):
1961    """ Datasets: gridded data such as model output, satellite imagery and drone imagery, held as a data stream with a
1962    mapping that says how its file is laid out. A dataset is read as a description, as tiles and slices of values, as
1963    samples at places and times, and as the display config that says how it is first shown.
1964
1965    Tiles and slices come back parsed from the hyperslab format the API sends. Times are ISO 8601 instants such as
1966    ``2025-02-10T02:00:00Z``. A variable that does not vary with time takes no ``time``, and one that does needs it.
1967    """
1968
1969    @abstractmethod
1970    def find_datasets(self, account_key: str) -> list[DatasetListingModel]:
1971        """ List the datasets of an account: the data streams visible to it that have a mapping, by name
1972
1973        :param str account_key: The key of the account
1974        :return: The datasets
1975        :rtype: list[DatasetListingModel]
1976        """
1977        pass
1978
1979    @abstractmethod
1980    def find_dataset_description(self, key: str) -> DatasetDescriptionModel:
1981        """ Find what a dataset is: its dimensions, coordinate sets and variables
1982
1983        :param str key: The key of the data stream that holds the dataset
1984        :return: The description
1985        :rtype: DatasetDescriptionModel
1986        """
1987        pass
1988
1989    @abstractmethod
1990    def update_dataset_properties(self, key: str, properties: DatasetPropertiesModel) -> DatasetListingModel:
1991        """ Replace a dataset's name, comment, tags, copyright and licence
1992
1993        :param str key: The key of the data stream that holds the dataset
1994        :param DatasetPropertiesModel properties: The properties to set
1995        :return: The dataset as it is now listed
1996        :rtype: DatasetListingModel
1997        """
1998        pass
1999
2000    @abstractmethod
2001    def update_dataset_mapping(self, key: str, mapping: str) -> DatasetMappingAppliedModel:
2002        """ Replace a dataset's mapping. The mapping is checked against the files of the set and refused, with each thing
2003        wrong at its path, if it does not agree with them
2004
2005        :param str key: The key of the data stream that holds the dataset
2006        :param str mapping: The mapping, as YAML text
2007        :return: The version stored and the description it gives
2008        :rtype: DatasetMappingAppliedModel
2009        """
2010        pass
2011
2012    @abstractmethod
2013    def find_dataset_tile(self, key: str, variable: str, z: int, x: int, y: int, time: Optional[str] = None,
2014                          level: Optional[int] = None) -> Hyperslab:
2015        """ Find one tile of a variable, on the web map grid (EPSG:3857) at zoom ``z``, as unstyled values
2016
2017        :param str key: The key of the data stream that holds the dataset
2018        :param str variable: The name of the variable in the mapping
2019        :param int z: The zoom of the tile
2020        :param int x: The column of the tile
2021        :param int y: The row of the tile
2022        :param Optional[str] time: The instant the tile is for, of a variable that varies with time
2023        :param Optional[int] level: The index of the level, of a variable with a vertical. The surface by default
2024        :return: The values of the tile
2025        :rtype: Hyperslab
2026        """
2027        pass
2028
2029    @abstractmethod
2030    def find_dataset_range(self, key: str, variable: str, time: Optional[str] = None,
2031                           level: Optional[int] = None) -> DatasetRangeModel:
2032        """ Find the range colours run between where none is chosen: the 2nd to the 98th percentile of the variable over
2033        the dataset's extent
2034
2035        :param str key: The key of the data stream that holds the dataset
2036        :param str variable: The name of the variable in the mapping
2037        :param Optional[str] time: The instant, of a variable that varies with time
2038        :param Optional[int] level: The index of the level, of a variable with a vertical
2039        :return: The low and high of the range
2040        :rtype: DatasetRangeModel
2041        """
2042        pass
2043
2044    @abstractmethod
2045    def find_dataset_edges(self, key: str, variable: str, z: int, x: int, y: int) -> DatasetEdgesModel:
2046        """ Find the edges of the cells that cross a tile, to draw the grid of a dataset
2047
2048        :param str key: The key of the data stream that holds the dataset
2049        :param str variable: The name of the variable in the mapping
2050        :param int z: The zoom of the tile
2051        :param int x: The column of the tile
2052        :param int y: The row of the tile
2053        :return: The lines, or none and ``tooMany`` where the tile holds too many nodes to draw
2054        :rtype: DatasetEdgesModel
2055        """
2056        pass
2057
2058    @abstractmethod
2059    def find_dataset_slice(self, key: str, variable: str, time: Optional[str] = None, level: Optional[int] = None,
2060                           start: Optional[str] = None, count: Optional[str] = None,
2061                           stride: Optional[str] = None) -> Hyperslab:
2062        """ Find a window of a variable in the dataset's own grid, as values
2063
2064        :param str key: The key of the data stream that holds the dataset
2065        :param str variable: The name of the variable in the mapping
2066        :param Optional[str] time: The instant the slice is for, of a variable that varies with time
2067        :param Optional[int] level: The index of the level, of a variable with a vertical
2068        :param Optional[str] start: The first row and column of the window. The origin by default
2069        :param Optional[str] count: The number of rows and columns to take. To the end of the grid by default
2070        :param Optional[str] stride: The step between rows and between columns. One by default
2071        :return: The values of the window
2072        :rtype: Hyperslab
2073        """
2074        pass
2075
2076    @abstractmethod
2077    def sample_dataset(self, key: str, request: DatasetSampleRequestModel) -> DatasetSampleResultModel:
2078        """ Sample a variable at places and times, such as those of a Site or a Track. Point values are interpolated
2079        across the cell and between the two records either side of the time, with no extrapolation. Give an ``observed``
2080        value with a position to get the comparison of the dataset with the observations in ``comparison``. A request
2081        over the cost limit is refused with the largest window or batch that is allowed, and is never truncated
2082
2083        :param str key: The key of the data stream that holds the dataset
2084        :param DatasetSampleRequestModel request: The variable and the positions
2085        :return: The samples, in the order of the positions
2086        :rtype: DatasetSampleResultModel
2087        """
2088        pass
2089
2090    @abstractmethod
2091    def find_dataset_display(self, key: str) -> DatasetDisplayModel:
2092        """ Find how a dataset is shown: the overrides by variable and how it is first shown on a map
2093
2094        :param str key: The key of the data stream that holds the dataset
2095        :return: The display config
2096        :rtype: DatasetDisplayModel
2097        """
2098        pass
2099
2100    @abstractmethod
2101    def update_dataset_display(self, key: str, display: str) -> DatasetDisplayModel:
2102        """ Replace how a dataset is shown. The display is checked against the mapping and refused, with each thing wrong
2103        at its path, if it does not agree with it
2104
2105        :param str key: The key of the data stream that holds the dataset
2106        :param str display: The display config, as YAML (or JSON) text, with keys such as ``fill_mode`` and ``axis_range``
2107        :return: The display as stored
2108        :rtype: DatasetDisplayModel
2109        """
2110        pass
2111
2112    @abstractmethod
2113    def find_dataset_members(self, key: str) -> DatasetSetModel:
2114        """ Find the files of a dataset's set in order along time, and the gaps between them
2115
2116        :param str key: The key of the data stream that holds the dataset
2117        :return: The members, the gaps and the rule for members that share time
2118        :rtype: DatasetSetModel
2119        """
2120        pass
2121
2122    @abstractmethod
2123    def verify_dataset_members(self, key: str, data_uuid: Optional[str] = None) -> DatasetSetModel:
2124        """ Check the files of a dataset's set against the size and SHA-256 registered. A file that differs is marked
2125        ``changed`` and one that is gone ``missing``
2126
2127        :param str key: The key of the data stream that holds the dataset
2128        :param Optional[str] data_uuid: Check this member only. All members by default
2129        :return: The members with their state
2130        :rtype: DatasetSetModel
2131        """
2132        pass

Datasets: gridded data such as model output, satellite imagery and drone imagery, held as a data stream with a mapping that says how its file is laid out. A dataset is read as a description, as tiles and slices of values, as samples at places and times, and as the display config that says how it is first shown.

Tiles and slices come back parsed from the hyperslab format the API sends. Times are ISO 8601 instants such as 2025-02-10T02:00:00Z. A variable that does not vary with time takes no time, and one that does needs it.

@abstractmethod
def find_datasets(self, account_key: str) -> list[inmotion.models.DatasetListingModel]:
1969    @abstractmethod
1970    def find_datasets(self, account_key: str) -> list[DatasetListingModel]:
1971        """ List the datasets of an account: the data streams visible to it that have a mapping, by name
1972
1973        :param str account_key: The key of the account
1974        :return: The datasets
1975        :rtype: list[DatasetListingModel]
1976        """
1977        pass

List the datasets of an account: the data streams visible to it that have a mapping, by name

Parameters
  • str account_key: The key of the account
Returns

The datasets

@abstractmethod
def find_dataset_description(self, key: str) -> inmotion.models.DatasetDescriptionModel:
1979    @abstractmethod
1980    def find_dataset_description(self, key: str) -> DatasetDescriptionModel:
1981        """ Find what a dataset is: its dimensions, coordinate sets and variables
1982
1983        :param str key: The key of the data stream that holds the dataset
1984        :return: The description
1985        :rtype: DatasetDescriptionModel
1986        """
1987        pass

Find what a dataset is: its dimensions, coordinate sets and variables

Parameters
  • str key: The key of the data stream that holds the dataset
Returns

The description

@abstractmethod
def update_dataset_properties( self, key: str, properties: inmotion.models.DatasetPropertiesModel) -> inmotion.models.DatasetListingModel:
1989    @abstractmethod
1990    def update_dataset_properties(self, key: str, properties: DatasetPropertiesModel) -> DatasetListingModel:
1991        """ Replace a dataset's name, comment, tags, copyright and licence
1992
1993        :param str key: The key of the data stream that holds the dataset
1994        :param DatasetPropertiesModel properties: The properties to set
1995        :return: The dataset as it is now listed
1996        :rtype: DatasetListingModel
1997        """
1998        pass

Replace a dataset's name, comment, tags, copyright and licence

Parameters
  • str key: The key of the data stream that holds the dataset
  • DatasetPropertiesModel properties: The properties to set
Returns

The dataset as it is now listed

@abstractmethod
def update_dataset_mapping( self, key: str, mapping: str) -> inmotion.models.DatasetMappingAppliedModel:
2000    @abstractmethod
2001    def update_dataset_mapping(self, key: str, mapping: str) -> DatasetMappingAppliedModel:
2002        """ Replace a dataset's mapping. The mapping is checked against the files of the set and refused, with each thing
2003        wrong at its path, if it does not agree with them
2004
2005        :param str key: The key of the data stream that holds the dataset
2006        :param str mapping: The mapping, as YAML text
2007        :return: The version stored and the description it gives
2008        :rtype: DatasetMappingAppliedModel
2009        """
2010        pass

Replace a dataset's mapping. The mapping is checked against the files of the set and refused, with each thing wrong at its path, if it does not agree with them

Parameters
  • str key: The key of the data stream that holds the dataset
  • str mapping: The mapping, as YAML text
Returns

The version stored and the description it gives

@abstractmethod
def find_dataset_tile( self, key: str, variable: str, z: int, x: int, y: int, time: Optional[str] = None, level: Optional[int] = None) -> inmotion.hyperslab.Hyperslab:
2012    @abstractmethod
2013    def find_dataset_tile(self, key: str, variable: str, z: int, x: int, y: int, time: Optional[str] = None,
2014                          level: Optional[int] = None) -> Hyperslab:
2015        """ Find one tile of a variable, on the web map grid (EPSG:3857) at zoom ``z``, as unstyled values
2016
2017        :param str key: The key of the data stream that holds the dataset
2018        :param str variable: The name of the variable in the mapping
2019        :param int z: The zoom of the tile
2020        :param int x: The column of the tile
2021        :param int y: The row of the tile
2022        :param Optional[str] time: The instant the tile is for, of a variable that varies with time
2023        :param Optional[int] level: The index of the level, of a variable with a vertical. The surface by default
2024        :return: The values of the tile
2025        :rtype: Hyperslab
2026        """
2027        pass

Find one tile of a variable, on the web map grid (EPSG:3857) at zoom z, as unstyled values

Parameters
  • str key: The key of the data stream that holds the dataset
  • str variable: The name of the variable in the mapping
  • int z: The zoom of the tile
  • int x: The column of the tile
  • int y: The row of the tile
  • Optional[str] time: The instant the tile is for, of a variable that varies with time
  • Optional[int] level: The index of the level, of a variable with a vertical. The surface by default
Returns

The values of the tile

@abstractmethod
def find_dataset_range( self, key: str, variable: str, time: Optional[str] = None, level: Optional[int] = None) -> inmotion.models.DatasetRangeModel:
2029    @abstractmethod
2030    def find_dataset_range(self, key: str, variable: str, time: Optional[str] = None,
2031                           level: Optional[int] = None) -> DatasetRangeModel:
2032        """ Find the range colours run between where none is chosen: the 2nd to the 98th percentile of the variable over
2033        the dataset's extent
2034
2035        :param str key: The key of the data stream that holds the dataset
2036        :param str variable: The name of the variable in the mapping
2037        :param Optional[str] time: The instant, of a variable that varies with time
2038        :param Optional[int] level: The index of the level, of a variable with a vertical
2039        :return: The low and high of the range
2040        :rtype: DatasetRangeModel
2041        """
2042        pass

Find the range colours run between where none is chosen: the 2nd to the 98th percentile of the variable over the dataset's extent

Parameters
  • str key: The key of the data stream that holds the dataset
  • str variable: The name of the variable in the mapping
  • Optional[str] time: The instant, of a variable that varies with time
  • Optional[int] level: The index of the level, of a variable with a vertical
Returns

The low and high of the range

@abstractmethod
def find_dataset_edges( self, key: str, variable: str, z: int, x: int, y: int) -> inmotion.models.DatasetEdgesModel:
2044    @abstractmethod
2045    def find_dataset_edges(self, key: str, variable: str, z: int, x: int, y: int) -> DatasetEdgesModel:
2046        """ Find the edges of the cells that cross a tile, to draw the grid of a dataset
2047
2048        :param str key: The key of the data stream that holds the dataset
2049        :param str variable: The name of the variable in the mapping
2050        :param int z: The zoom of the tile
2051        :param int x: The column of the tile
2052        :param int y: The row of the tile
2053        :return: The lines, or none and ``tooMany`` where the tile holds too many nodes to draw
2054        :rtype: DatasetEdgesModel
2055        """
2056        pass

Find the edges of the cells that cross a tile, to draw the grid of a dataset

Parameters
  • str key: The key of the data stream that holds the dataset
  • str variable: The name of the variable in the mapping
  • int z: The zoom of the tile
  • int x: The column of the tile
  • int y: The row of the tile
Returns

The lines, or none and tooMany where the tile holds too many nodes to draw

@abstractmethod
def find_dataset_slice( self, key: str, variable: str, time: Optional[str] = None, level: Optional[int] = None, start: Optional[str] = None, count: Optional[str] = None, stride: Optional[str] = None) -> inmotion.hyperslab.Hyperslab:
2058    @abstractmethod
2059    def find_dataset_slice(self, key: str, variable: str, time: Optional[str] = None, level: Optional[int] = None,
2060                           start: Optional[str] = None, count: Optional[str] = None,
2061                           stride: Optional[str] = None) -> Hyperslab:
2062        """ Find a window of a variable in the dataset's own grid, as values
2063
2064        :param str key: The key of the data stream that holds the dataset
2065        :param str variable: The name of the variable in the mapping
2066        :param Optional[str] time: The instant the slice is for, of a variable that varies with time
2067        :param Optional[int] level: The index of the level, of a variable with a vertical
2068        :param Optional[str] start: The first row and column of the window. The origin by default
2069        :param Optional[str] count: The number of rows and columns to take. To the end of the grid by default
2070        :param Optional[str] stride: The step between rows and between columns. One by default
2071        :return: The values of the window
2072        :rtype: Hyperslab
2073        """
2074        pass

Find a window of a variable in the dataset's own grid, as values

Parameters
  • str key: The key of the data stream that holds the dataset
  • str variable: The name of the variable in the mapping
  • Optional[str] time: The instant the slice is for, of a variable that varies with time
  • Optional[int] level: The index of the level, of a variable with a vertical
  • Optional[str] start: The first row and column of the window. The origin by default
  • Optional[str] count: The number of rows and columns to take. To the end of the grid by default
  • Optional[str] stride: The step between rows and between columns. One by default
Returns

The values of the window

@abstractmethod
def sample_dataset( self, key: str, request: inmotion.models.DatasetSampleRequestModel) -> inmotion.models.DatasetSampleResultModel:
2076    @abstractmethod
2077    def sample_dataset(self, key: str, request: DatasetSampleRequestModel) -> DatasetSampleResultModel:
2078        """ Sample a variable at places and times, such as those of a Site or a Track. Point values are interpolated
2079        across the cell and between the two records either side of the time, with no extrapolation. Give an ``observed``
2080        value with a position to get the comparison of the dataset with the observations in ``comparison``. A request
2081        over the cost limit is refused with the largest window or batch that is allowed, and is never truncated
2082
2083        :param str key: The key of the data stream that holds the dataset
2084        :param DatasetSampleRequestModel request: The variable and the positions
2085        :return: The samples, in the order of the positions
2086        :rtype: DatasetSampleResultModel
2087        """
2088        pass

Sample a variable at places and times, such as those of a Site or a Track. Point values are interpolated across the cell and between the two records either side of the time, with no extrapolation. Give an observed value with a position to get the comparison of the dataset with the observations in comparison. A request over the cost limit is refused with the largest window or batch that is allowed, and is never truncated

Parameters
  • str key: The key of the data stream that holds the dataset
  • DatasetSampleRequestModel request: The variable and the positions
Returns

The samples, in the order of the positions

@abstractmethod
def find_dataset_display(self, key: str) -> inmotion.models.DatasetDisplayModel:
2090    @abstractmethod
2091    def find_dataset_display(self, key: str) -> DatasetDisplayModel:
2092        """ Find how a dataset is shown: the overrides by variable and how it is first shown on a map
2093
2094        :param str key: The key of the data stream that holds the dataset
2095        :return: The display config
2096        :rtype: DatasetDisplayModel
2097        """
2098        pass

Find how a dataset is shown: the overrides by variable and how it is first shown on a map

Parameters
  • str key: The key of the data stream that holds the dataset
Returns

The display config

@abstractmethod
def update_dataset_display(self, key: str, display: str) -> inmotion.models.DatasetDisplayModel:
2100    @abstractmethod
2101    def update_dataset_display(self, key: str, display: str) -> DatasetDisplayModel:
2102        """ Replace how a dataset is shown. The display is checked against the mapping and refused, with each thing wrong
2103        at its path, if it does not agree with it
2104
2105        :param str key: The key of the data stream that holds the dataset
2106        :param str display: The display config, as YAML (or JSON) text, with keys such as ``fill_mode`` and ``axis_range``
2107        :return: The display as stored
2108        :rtype: DatasetDisplayModel
2109        """
2110        pass

Replace how a dataset is shown. The display is checked against the mapping and refused, with each thing wrong at its path, if it does not agree with it

Parameters
  • str key: The key of the data stream that holds the dataset
  • str display: The display config, as YAML (or JSON) text, with keys such as fill_mode and axis_range
Returns

The display as stored

@abstractmethod
def find_dataset_members(self, key: str) -> inmotion.models.DatasetSetModel:
2112    @abstractmethod
2113    def find_dataset_members(self, key: str) -> DatasetSetModel:
2114        """ Find the files of a dataset's set in order along time, and the gaps between them
2115
2116        :param str key: The key of the data stream that holds the dataset
2117        :return: The members, the gaps and the rule for members that share time
2118        :rtype: DatasetSetModel
2119        """
2120        pass

Find the files of a dataset's set in order along time, and the gaps between them

Parameters
  • str key: The key of the data stream that holds the dataset
Returns

The members, the gaps and the rule for members that share time

@abstractmethod
def verify_dataset_members( self, key: str, data_uuid: Optional[str] = None) -> inmotion.models.DatasetSetModel:
2122    @abstractmethod
2123    def verify_dataset_members(self, key: str, data_uuid: Optional[str] = None) -> DatasetSetModel:
2124        """ Check the files of a dataset's set against the size and SHA-256 registered. A file that differs is marked
2125        ``changed`` and one that is gone ``missing``
2126
2127        :param str key: The key of the data stream that holds the dataset
2128        :param Optional[str] data_uuid: Check this member only. All members by default
2129        :return: The members with their state
2130        :rtype: DatasetSetModel
2131        """
2132        pass

Check the files of a dataset's set against the size and SHA-256 registered. A file that differs is marked changed and one that is gone missing

Parameters
  • str key: The key of the data stream that holds the dataset
  • Optional[str] data_uuid: Check this member only. All members by default
Returns

The members with their state

class InMotionDevKeys(abc.ABC):
1268class InMotionDevKeys(ABC):
1269    @abstractmethod
1270    def find_dev_keys(self, account_key: str) -> list[AccountDevKeyModel]:
1271        """ Retrieve the developer keys associated with an account
1272
1273        :param str account_key: The unique key of the account
1274        :return: The account's developer keys
1275        :rtype: list[AccountDevKeyModel]
1276        """
1277        pass
1278
1279    @abstractmethod
1280    def create_dev_key(self, account_key: str, creator: AccountDevKeyCreatorModel) -> AccountDevKeyModel:
1281        """ Create a new developer key for an account
1282
1283        :param str account_key: The unique key of the account
1284        :param AccountDevKeyCreatorModel creator: The definition of the developer key to create
1285        :return: The created developer key
1286        :rtype: AccountDevKeyModel
1287        """
1288        pass
1289
1290    @abstractmethod
1291    def update_dev_key(self, account_key: str, dev_key: str, updator: AccountDevKeyUpdatorModel) -> AccountDevKeyModel:
1292        """ Update an existing developer key
1293
1294        :param str account_key: The unique key of the account
1295        :param str dev_key: The developer key to update
1296        :param AccountDevKeyUpdatorModel updator: The updated fields for the developer key
1297        :return: The updated developer key
1298        :rtype: AccountDevKeyModel
1299        """
1300        pass
1301
1302    @abstractmethod
1303    def delete_dev_key(self, account_key: str, dev_key: str) -> AccountDevKeyResponseModel:
1304        """ Delete a developer key from an account
1305
1306        :param str account_key: The unique key of the account
1307        :param str dev_key: The developer key to delete
1308        :return: The result of the delete operation
1309        :rtype: AccountDevKeyResponseModel
1310        """
1311        pass
1312
1313    @abstractmethod
1314    def find_dev_key(self, account_key: str, dev_key: str) -> AccountDevKeyModel:
1315        """ Find a specific developer key belonging to an account
1316
1317        :param str account_key: The unique key of the account
1318        :param str dev_key: The developer key to retrieve
1319        :return: The developer key
1320        :rtype: AccountDevKeyModel
1321        """
1322        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def find_dev_keys(self, account_key: str) -> list[inmotion.models.AccountDevKeyModel]:
1269    @abstractmethod
1270    def find_dev_keys(self, account_key: str) -> list[AccountDevKeyModel]:
1271        """ Retrieve the developer keys associated with an account
1272
1273        :param str account_key: The unique key of the account
1274        :return: The account's developer keys
1275        :rtype: list[AccountDevKeyModel]
1276        """
1277        pass

Retrieve the developer keys associated with an account

Parameters
  • str account_key: The unique key of the account
Returns

The account's developer keys

@abstractmethod
def create_dev_key( self, account_key: str, creator: inmotion.models.AccountDevKeyCreatorModel) -> inmotion.models.AccountDevKeyModel:
1279    @abstractmethod
1280    def create_dev_key(self, account_key: str, creator: AccountDevKeyCreatorModel) -> AccountDevKeyModel:
1281        """ Create a new developer key for an account
1282
1283        :param str account_key: The unique key of the account
1284        :param AccountDevKeyCreatorModel creator: The definition of the developer key to create
1285        :return: The created developer key
1286        :rtype: AccountDevKeyModel
1287        """
1288        pass

Create a new developer key for an account

Parameters
  • str account_key: The unique key of the account
  • AccountDevKeyCreatorModel creator: The definition of the developer key to create
Returns

The created developer key

@abstractmethod
def update_dev_key( self, account_key: str, dev_key: str, updator: inmotion.models.AccountDevKeyUpdatorModel) -> inmotion.models.AccountDevKeyModel:
1290    @abstractmethod
1291    def update_dev_key(self, account_key: str, dev_key: str, updator: AccountDevKeyUpdatorModel) -> AccountDevKeyModel:
1292        """ Update an existing developer key
1293
1294        :param str account_key: The unique key of the account
1295        :param str dev_key: The developer key to update
1296        :param AccountDevKeyUpdatorModel updator: The updated fields for the developer key
1297        :return: The updated developer key
1298        :rtype: AccountDevKeyModel
1299        """
1300        pass

Update an existing developer key

Parameters
  • str account_key: The unique key of the account
  • str dev_key: The developer key to update
  • AccountDevKeyUpdatorModel updator: The updated fields for the developer key
Returns

The updated developer key

@abstractmethod
def delete_dev_key( self, account_key: str, dev_key: str) -> inmotion.models.AccountDevKeyResponseModel:
1302    @abstractmethod
1303    def delete_dev_key(self, account_key: str, dev_key: str) -> AccountDevKeyResponseModel:
1304        """ Delete a developer key from an account
1305
1306        :param str account_key: The unique key of the account
1307        :param str dev_key: The developer key to delete
1308        :return: The result of the delete operation
1309        :rtype: AccountDevKeyResponseModel
1310        """
1311        pass

Delete a developer key from an account

Parameters
  • str account_key: The unique key of the account
  • str dev_key: The developer key to delete
Returns

The result of the delete operation

@abstractmethod
def find_dev_key( self, account_key: str, dev_key: str) -> inmotion.models.AccountDevKeyModel:
1313    @abstractmethod
1314    def find_dev_key(self, account_key: str, dev_key: str) -> AccountDevKeyModel:
1315        """ Find a specific developer key belonging to an account
1316
1317        :param str account_key: The unique key of the account
1318        :param str dev_key: The developer key to retrieve
1319        :return: The developer key
1320        :rtype: AccountDevKeyModel
1321        """
1322        pass

Find a specific developer key belonging to an account

Parameters
  • str account_key: The unique key of the account
  • str dev_key: The developer key to retrieve
Returns

The developer key

class InMotionEvents(abc.ABC):
628class InMotionEvents(ABC):
629    """ Event management: an Activity peer of Track/Site whose payload is arbitrary (photo,
630    sqlite file, diagnostics, ...) rather than structured hyperslab data. An event is a single
631    point in space/time, optionally carrying a thumbnail/icon. """
632
633    @abstractmethod
634    def create_event(self, event: EventCreatorModel) -> EventDetailsModel:
635        """ Create an event associated with a specific account
636
637        :param EventCreatorModel event: The definition of the event to create. A captured
638            location is required; a thumbnail/icon is optional.
639        :return: The created event's details
640        :rtype: EventDetailsModel
641        """
642        pass
643
644    @abstractmethod
645    def update_event(self, key: str, event: EventUpdateModel) -> EventDetailsModel:
646        """ Update an existing event's underlying data stream metadata, and optionally its
647        captured location and/or thumbnail. Omitting `location` or `thumbnail` leaves the
648        existing value unchanged - there is no way to clear either back to unset once set.
649
650        :param str key: The unique key of the event to update
651        :param EventUpdateModel event: The updated definition of the event
652        :return: The updated event's details
653        :rtype: EventDetailsModel
654        """
655        pass
656
657    @abstractmethod
658    def find_event(self, key: str) -> EventDetailsModel:
659        """ Find an event by its unique key
660
661        :param str key: The unique key of the event
662        :return: The event's details
663        :rtype: EventDetailsModel
664        """
665        pass
666
667    @abstractmethod
668    def delete_event(self, key: str) -> None:
669        """ Delete an event by its unique key, along with all of its associated data
670
671        :param str key: The unique key of the event to delete
672        """
673        pass
674
675    @abstractmethod
676    def unlock_event(self, key: str) -> None:
677        """ Unlock an event so that it can be modified or updated again after having been locked
678
679        :param str key: The unique key of the event to unlock
680        """
681        pass
682
683    @abstractmethod
684    def find_events(self, data_stream_filter: DataStreamFilterModel) -> list[DataStreamSummaryModel]:
685        """ Find event summaries matching a data stream filter (account, name, source, etc.),
686        constrained server-side to events regardless of what's supplied
687
688        :param DataStreamFilterModel data_stream_filter: The filter to apply to the search
689        :return: Summaries of the matching events
690        :rtype: list[DataStreamSummaryModel]
691        """
692        pass
693
694    @abstractmethod
695    def find_nearby_events(self, nearby_filter: EventNearbyFilterModel) -> list[EventLocationSummaryModel]:
696        """ Find events within a spatio-temporal bounding box, constrained to a supplied set of
697        accounts (never unconstrained - an empty `accounts` list returns no results)
698
699        :param EventNearbyFilterModel nearby_filter: The accounts and spatio-temporal bounds to search
700        :return: The events found within the requested window
701        :rtype: list[EventLocationSummaryModel]
702        """
703        pass

Event management: an Activity peer of Track/Site whose payload is arbitrary (photo, sqlite file, diagnostics, ...) rather than structured hyperslab data. An event is a single point in space/time, optionally carrying a thumbnail/icon.

@abstractmethod
def create_event( self, event: inmotion.models.EventCreatorModel) -> inmotion.models.EventDetailsModel:
633    @abstractmethod
634    def create_event(self, event: EventCreatorModel) -> EventDetailsModel:
635        """ Create an event associated with a specific account
636
637        :param EventCreatorModel event: The definition of the event to create. A captured
638            location is required; a thumbnail/icon is optional.
639        :return: The created event's details
640        :rtype: EventDetailsModel
641        """
642        pass

Create an event associated with a specific account

Parameters
  • EventCreatorModel event: The definition of the event to create. A captured location is required; a thumbnail/icon is optional.
Returns

The created event's details

@abstractmethod
def update_event( self, key: str, event: inmotion.models.EventUpdateModel) -> inmotion.models.EventDetailsModel:
644    @abstractmethod
645    def update_event(self, key: str, event: EventUpdateModel) -> EventDetailsModel:
646        """ Update an existing event's underlying data stream metadata, and optionally its
647        captured location and/or thumbnail. Omitting `location` or `thumbnail` leaves the
648        existing value unchanged - there is no way to clear either back to unset once set.
649
650        :param str key: The unique key of the event to update
651        :param EventUpdateModel event: The updated definition of the event
652        :return: The updated event's details
653        :rtype: EventDetailsModel
654        """
655        pass

Update an existing event's underlying data stream metadata, and optionally its captured location and/or thumbnail. Omitting location or thumbnail leaves the existing value unchanged - there is no way to clear either back to unset once set.

Parameters
  • str key: The unique key of the event to update
  • EventUpdateModel event: The updated definition of the event
Returns

The updated event's details

@abstractmethod
def find_event(self, key: str) -> inmotion.models.EventDetailsModel:
657    @abstractmethod
658    def find_event(self, key: str) -> EventDetailsModel:
659        """ Find an event by its unique key
660
661        :param str key: The unique key of the event
662        :return: The event's details
663        :rtype: EventDetailsModel
664        """
665        pass

Find an event by its unique key

Parameters
  • str key: The unique key of the event
Returns

The event's details

@abstractmethod
def delete_event(self, key: str) -> None:
667    @abstractmethod
668    def delete_event(self, key: str) -> None:
669        """ Delete an event by its unique key, along with all of its associated data
670
671        :param str key: The unique key of the event to delete
672        """
673        pass

Delete an event by its unique key, along with all of its associated data

Parameters
  • str key: The unique key of the event to delete
@abstractmethod
def unlock_event(self, key: str) -> None:
675    @abstractmethod
676    def unlock_event(self, key: str) -> None:
677        """ Unlock an event so that it can be modified or updated again after having been locked
678
679        :param str key: The unique key of the event to unlock
680        """
681        pass

Unlock an event so that it can be modified or updated again after having been locked

Parameters
  • str key: The unique key of the event to unlock
@abstractmethod
def find_events( self, data_stream_filter: inmotion.models.DataStreamFilterModel) -> list[inmotion.models.DataStreamSummaryModel]:
683    @abstractmethod
684    def find_events(self, data_stream_filter: DataStreamFilterModel) -> list[DataStreamSummaryModel]:
685        """ Find event summaries matching a data stream filter (account, name, source, etc.),
686        constrained server-side to events regardless of what's supplied
687
688        :param DataStreamFilterModel data_stream_filter: The filter to apply to the search
689        :return: Summaries of the matching events
690        :rtype: list[DataStreamSummaryModel]
691        """
692        pass

Find event summaries matching a data stream filter (account, name, source, etc.), constrained server-side to events regardless of what's supplied

Parameters
  • DataStreamFilterModel data_stream_filter: The filter to apply to the search
Returns

Summaries of the matching events

@abstractmethod
def find_nearby_events( self, nearby_filter: inmotion.models.EventNearbyFilterModel) -> list[inmotion.models.EventLocationSummaryModel]:
694    @abstractmethod
695    def find_nearby_events(self, nearby_filter: EventNearbyFilterModel) -> list[EventLocationSummaryModel]:
696        """ Find events within a spatio-temporal bounding box, constrained to a supplied set of
697        accounts (never unconstrained - an empty `accounts` list returns no results)
698
699        :param EventNearbyFilterModel nearby_filter: The accounts and spatio-temporal bounds to search
700        :return: The events found within the requested window
701        :rtype: list[EventLocationSummaryModel]
702        """
703        pass

Find events within a spatio-temporal bounding box, constrained to a supplied set of accounts (never unconstrained - an empty accounts list returns no results)

Parameters
  • EventNearbyFilterModel nearby_filter: The accounts and spatio-temporal bounds to search
Returns

The events found within the requested window

class InMotionExplorer(abc.ABC):
2135class InMotionExplorer(ABC):
2136    """ The Explorer catalog: the Tracks, Sites, shapes, rasters and grids of every account the caller may read, found by
2137    kind, category, place, time or text. Leaving ``scope`` out resolves to every account the caller can access whose
2138    subscription includes Explore. Times are milliseconds since the epoch and a place is a bounding box in degrees.
2139    """
2140
2141    @abstractmethod
2142    def find_catalog(self, scope: Optional[list[str]] = None, kinds: Optional[list[str]] = None,
2143                     categories: Optional[list[str]] = None, exact_categories: bool = False,
2144                     profiles: Optional[list[str]] = None, text: Optional[str] = None,
2145                     bbox: Optional[ExplorerBBoxModel] = None, time_from: Optional[int] = None,
2146                     time_to: Optional[int] = None, limit: Optional[int] = None, cursor: Optional[str] = None,
2147                     ids: Optional[list[str]] = None, tags: Optional[list[str]] = None) -> ExplorerCatalogModel:
2148        """ Find the layers that match, newest first, with the counts of each kind, category and profile among them. A
2149        page holds at most 500 layers; ``nextCursor`` fetches the next
2150
2151        :param Optional[list[str]] scope: The accounts to look in
2152        :param Optional[list[str]] kinds: Keep layers of these kinds: ``site``, ``track``, ``shape``, ``raster``, ``grid``, ``mesh``
2153        :param Optional[list[str]] categories: Keep layers in these categories and those beneath them
2154        :param bool exact_categories: Keep only the layers in exactly the given categories
2155        :param Optional[list[str]] profiles: Keep layers of these profiles
2156        :param Optional[str] text: Text found in a layer's name or category, ignoring case
2157        :param Optional[ExplorerBBoxModel] bbox: Keep layers whose envelope meets this region
2158        :param Optional[int] time_from: Keep layers that reach this time, in milliseconds
2159        :param Optional[int] time_to: Keep layers that start by this time, in milliseconds
2160        :param Optional[int] limit: The most layers to return
2161        :param Optional[str] cursor: The ``nextCursor`` of the previous page
2162        :param Optional[list[str]] ids: Keep only the layers with these identifiers
2163        :param Optional[list[str]] tags: Keep layers that carry any of these tags
2164        :return: A page of the catalog
2165        :rtype: ExplorerCatalogModel
2166        """
2167        pass
2168
2169    @abstractmethod
2170    def find_clusters(self, cell: float, scope: Optional[list[str]] = None, kinds: Optional[list[str]] = None,
2171                      categories: Optional[list[str]] = None, exact_categories: bool = False,
2172                      profiles: Optional[list[str]] = None, text: Optional[str] = None,
2173                      bbox: Optional[ExplorerBBoxModel] = None, time_from: Optional[int] = None,
2174                      time_to: Optional[int] = None, ids: Optional[list[str]] = None,
2175                      tags: Optional[list[str]] = None) -> list[ExplorerClusterModel]:
2176        """ Find the matching layers grouped into the cells of a grid
2177
2178        :param float cell: The width and height of a cell, in degrees (between 0.00001 and 90)
2179        :return: The cells that hold layers
2180        :rtype: list[ExplorerClusterModel]
2181        """
2182        pass
2183
2184    @abstractmethod
2185    def find_time_profile(self, buckets: Optional[int] = None, scope: Optional[list[str]] = None,
2186                          kinds: Optional[list[str]] = None, categories: Optional[list[str]] = None,
2187                          exact_categories: bool = False, profiles: Optional[list[str]] = None,
2188                          text: Optional[str] = None, bbox: Optional[ExplorerBBoxModel] = None,
2189                          ids: Optional[list[str]] = None, tags: Optional[list[str]] = None) -> ExplorerTimeProfileModel:
2190        """ Find all the time the matching layers cover, and how many end in each of ``buckets`` equal slices of it
2191
2192        :param Optional[int] buckets: Slices of the time covered (default 60, at most 240)
2193        :return: The time covered and the counts
2194        :rtype: ExplorerTimeProfileModel
2195        """
2196        pass

The Explorer catalog: the Tracks, Sites, shapes, rasters and grids of every account the caller may read, found by kind, category, place, time or text. Leaving scope out resolves to every account the caller can access whose subscription includes Explore. Times are milliseconds since the epoch and a place is a bounding box in degrees.

@abstractmethod
def find_catalog( self, scope: Optional[list[str]] = None, kinds: Optional[list[str]] = None, categories: Optional[list[str]] = None, exact_categories: bool = False, profiles: Optional[list[str]] = None, text: Optional[str] = None, bbox: Optional[inmotion.models.ExplorerBBoxModel] = None, time_from: Optional[int] = None, time_to: Optional[int] = None, limit: Optional[int] = None, cursor: Optional[str] = None, ids: Optional[list[str]] = None, tags: Optional[list[str]] = None) -> inmotion.models.ExplorerCatalogModel:
2141    @abstractmethod
2142    def find_catalog(self, scope: Optional[list[str]] = None, kinds: Optional[list[str]] = None,
2143                     categories: Optional[list[str]] = None, exact_categories: bool = False,
2144                     profiles: Optional[list[str]] = None, text: Optional[str] = None,
2145                     bbox: Optional[ExplorerBBoxModel] = None, time_from: Optional[int] = None,
2146                     time_to: Optional[int] = None, limit: Optional[int] = None, cursor: Optional[str] = None,
2147                     ids: Optional[list[str]] = None, tags: Optional[list[str]] = None) -> ExplorerCatalogModel:
2148        """ Find the layers that match, newest first, with the counts of each kind, category and profile among them. A
2149        page holds at most 500 layers; ``nextCursor`` fetches the next
2150
2151        :param Optional[list[str]] scope: The accounts to look in
2152        :param Optional[list[str]] kinds: Keep layers of these kinds: ``site``, ``track``, ``shape``, ``raster``, ``grid``, ``mesh``
2153        :param Optional[list[str]] categories: Keep layers in these categories and those beneath them
2154        :param bool exact_categories: Keep only the layers in exactly the given categories
2155        :param Optional[list[str]] profiles: Keep layers of these profiles
2156        :param Optional[str] text: Text found in a layer's name or category, ignoring case
2157        :param Optional[ExplorerBBoxModel] bbox: Keep layers whose envelope meets this region
2158        :param Optional[int] time_from: Keep layers that reach this time, in milliseconds
2159        :param Optional[int] time_to: Keep layers that start by this time, in milliseconds
2160        :param Optional[int] limit: The most layers to return
2161        :param Optional[str] cursor: The ``nextCursor`` of the previous page
2162        :param Optional[list[str]] ids: Keep only the layers with these identifiers
2163        :param Optional[list[str]] tags: Keep layers that carry any of these tags
2164        :return: A page of the catalog
2165        :rtype: ExplorerCatalogModel
2166        """
2167        pass

Find the layers that match, newest first, with the counts of each kind, category and profile among them. A page holds at most 500 layers; nextCursor fetches the next

Parameters
  • Optional[list[str]] scope: The accounts to look in
  • Optional[list[str]] kinds: Keep layers of these kinds: site, track, shape, raster, grid, mesh
  • Optional[list[str]] categories: Keep layers in these categories and those beneath them
  • bool exact_categories: Keep only the layers in exactly the given categories
  • Optional[list[str]] profiles: Keep layers of these profiles
  • Optional[str] text: Text found in a layer's name or category, ignoring case
  • Optional[ExplorerBBoxModel] bbox: Keep layers whose envelope meets this region
  • Optional[int] time_from: Keep layers that reach this time, in milliseconds
  • Optional[int] time_to: Keep layers that start by this time, in milliseconds
  • Optional[int] limit: The most layers to return
  • Optional[str] cursor: The nextCursor of the previous page
  • Optional[list[str]] ids: Keep only the layers with these identifiers
  • Optional[list[str]] tags: Keep layers that carry any of these tags
Returns

A page of the catalog

@abstractmethod
def find_clusters( self, cell: float, scope: Optional[list[str]] = None, kinds: Optional[list[str]] = None, categories: Optional[list[str]] = None, exact_categories: bool = False, profiles: Optional[list[str]] = None, text: Optional[str] = None, bbox: Optional[inmotion.models.ExplorerBBoxModel] = None, time_from: Optional[int] = None, time_to: Optional[int] = None, ids: Optional[list[str]] = None, tags: Optional[list[str]] = None) -> list[inmotion.models.ExplorerClusterModel]:
2169    @abstractmethod
2170    def find_clusters(self, cell: float, scope: Optional[list[str]] = None, kinds: Optional[list[str]] = None,
2171                      categories: Optional[list[str]] = None, exact_categories: bool = False,
2172                      profiles: Optional[list[str]] = None, text: Optional[str] = None,
2173                      bbox: Optional[ExplorerBBoxModel] = None, time_from: Optional[int] = None,
2174                      time_to: Optional[int] = None, ids: Optional[list[str]] = None,
2175                      tags: Optional[list[str]] = None) -> list[ExplorerClusterModel]:
2176        """ Find the matching layers grouped into the cells of a grid
2177
2178        :param float cell: The width and height of a cell, in degrees (between 0.00001 and 90)
2179        :return: The cells that hold layers
2180        :rtype: list[ExplorerClusterModel]
2181        """
2182        pass

Find the matching layers grouped into the cells of a grid

Parameters
  • float cell: The width and height of a cell, in degrees (between 0.00001 and 90)
Returns

The cells that hold layers

@abstractmethod
def find_time_profile( self, buckets: Optional[int] = None, scope: Optional[list[str]] = None, kinds: Optional[list[str]] = None, categories: Optional[list[str]] = None, exact_categories: bool = False, profiles: Optional[list[str]] = None, text: Optional[str] = None, bbox: Optional[inmotion.models.ExplorerBBoxModel] = None, ids: Optional[list[str]] = None, tags: Optional[list[str]] = None) -> inmotion.models.ExplorerTimeProfileModel:
2184    @abstractmethod
2185    def find_time_profile(self, buckets: Optional[int] = None, scope: Optional[list[str]] = None,
2186                          kinds: Optional[list[str]] = None, categories: Optional[list[str]] = None,
2187                          exact_categories: bool = False, profiles: Optional[list[str]] = None,
2188                          text: Optional[str] = None, bbox: Optional[ExplorerBBoxModel] = None,
2189                          ids: Optional[list[str]] = None, tags: Optional[list[str]] = None) -> ExplorerTimeProfileModel:
2190        """ Find all the time the matching layers cover, and how many end in each of ``buckets`` equal slices of it
2191
2192        :param Optional[int] buckets: Slices of the time covered (default 60, at most 240)
2193        :return: The time covered and the counts
2194        :rtype: ExplorerTimeProfileModel
2195        """
2196        pass

Find all the time the matching layers cover, and how many end in each of buckets equal slices of it

Parameters
  • Optional[int] buckets: Slices of the time covered (default 60, at most 240)
Returns

The time covered and the counts

class InMotionFolio(abc.ABC):
1659class InMotionFolio(ABC):
1660    """ Folio management: a tree-structured document attached to an account - a versioned root
1661    plus an arbitrary tree of named sections, each holding items that are either inline
1662    structured text or references to an Activity, DataStream, or another Folio. """
1663
1664    @abstractmethod
1665    def create_folio(self, folio: FolioModel) -> FolioDetailsModel:
1666        """ Create a new, top-level, account-owned folio
1667
1668        :param FolioModel folio: The definition of the folio to create. `templateYaml` may be
1669            supplied to attach a validation template, fixed for the folio's lifetime.
1670        :return: The created folio's details
1671        :rtype: FolioDetailsModel
1672        """
1673        pass
1674
1675    @abstractmethod
1676    def update_folio(self, key: str, folio: FolioModel) -> FolioDetailsModel:
1677        """ Update a folio's own metadata (name, description, folioType). Does not touch its
1678        section tree - use the section/item methods below for that.
1679
1680        :param str key: The unique key of the folio to update
1681        :param FolioModel folio: The updated definition of the folio
1682        :return: The updated folio's details
1683        :rtype: FolioDetailsModel
1684        """
1685        pass
1686
1687    @abstractmethod
1688    def set_folio_locked(self, key: str, locked: bool) -> FolioDetailsModel:
1689        """ Lock or unlock a folio against further Contributor edits, independent of how it was
1690        created. Any Contributor (or above) may call this at any time, regardless of the folio's
1691        current locked state - unlike update_folio, this is never blocked by the folio being
1692        locked or API-created.
1693
1694        :param str key: The unique key of the folio
1695        :param bool locked: True to lock, False to unlock
1696        :return: The folio's details, with its updated locked state
1697        :rtype: FolioDetailsModel
1698        """
1699        pass
1700
1701    @abstractmethod
1702    def find_folio(self, key: str) -> FolioDetailsModel:
1703        """ Find a folio by its unique key, including its full section tree
1704
1705        :param str key: The unique key of the folio
1706        :return: The folio's details
1707        :rtype: FolioDetailsModel
1708        """
1709        pass
1710
1711    @abstractmethod
1712    def delete_folio(self, key: str) -> None:
1713        """ Delete a folio by its unique key, along with its entire section tree
1714
1715        :param str key: The unique key of the folio to delete
1716        """
1717        pass
1718
1719    @abstractmethod
1720    def find_folios(self, account_key: str, name: Optional[str] = None, folio_type: Optional[str] = None) -> list[FolioSummaryModel]:
1721        """ List folio summaries for an account, optionally filtered by name and/or folio type
1722
1723        :param str account_key: The unique key of the account
1724        :param Optional[str] name: An optional name to filter by
1725        :param Optional[str] folio_type: An optional folio type to filter by
1726        :return: The matching folio summaries
1727        :rtype: list[FolioSummaryModel]
1728        """
1729        pass
1730
1731    @abstractmethod
1732    def find_folios_by_reference(self, account_key: str, ref_key: str) -> list[FolioSummaryModel]:
1733        """ List folio summaries for an account that contain at least one item (Activity,
1734        DataStream, or Folio reference) pointing at the given key
1735
1736        :param str account_key: The unique key of the account
1737        :param str ref_key: The key of the referenced Activity, DataStream, or Folio
1738        :return: The matching folio summaries
1739        :rtype: list[FolioSummaryModel]
1740        """
1741        pass
1742
1743    @abstractmethod
1744    def find_section(self, key: str, path: Optional[str] = None, deep: bool = False) -> FolioRootModel | FolioSectionModel:
1745        """ Find the root or a named section of a folio's tree, addressed by `path`
1746
1747        :param str key: The unique key of the folio
1748        :param Optional[str] path: "/"-separated section path from the root, e.g.
1749            "Eye Tests/2026-08-04". Omitted or empty addresses the root.
1750        :param bool deep: If True, include the full subtree beneath the addressed section, not
1751            just its immediate children
1752        :return: The root (if `path` addresses it) or the section at `path`
1753        :rtype: FolioRootModel | FolioSectionModel
1754        """
1755        pass
1756
1757    @abstractmethod
1758    def create_section(self, key: str, section: FolioSectionCreateModel, path: Optional[str] = None) -> None:
1759        """ Add a new named section as a child of the section (or root) addressed by `path`
1760
1761        :param str key: The unique key of the folio
1762        :param FolioSectionCreateModel section: The definition of the section to create
1763        :param Optional[str] path: "/"-separated parent section path from the root. Omitted or
1764            empty adds the new section directly beneath the root.
1765        """
1766        pass
1767
1768    @abstractmethod
1769    def update_section(self, key: str, section: FolioSectionUpdateModel, path: Optional[str] = None) -> None:
1770        """ Update the section (or root) addressed by `path`. Only the fields supplied on
1771        `section` change; omitted fields are left as-is.
1772
1773        :param str key: The unique key of the folio
1774        :param FolioSectionUpdateModel section: The fields to update
1775        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1776            addresses the root.
1777        """
1778        pass
1779
1780    @abstractmethod
1781    def delete_section(self, key: str, path: Optional[str] = None, cascade: bool = False) -> None:
1782        """ Delete the section addressed by `path` (the root itself cannot be deleted this way -
1783        use delete_folio instead)
1784
1785        :param str key: The unique key of the folio
1786        :param Optional[str] path: "/"-separated section path from the root
1787        :param bool cascade: If True, delete the section's contents (sub-sections and items)
1788            along with it - otherwise fails if the section has children
1789        """
1790        pass
1791
1792    @abstractmethod
1793    def add_items(self, key: str, items: list[FolioItemModel], path: Optional[str] = None) -> None:
1794        """ Add one or more items to the section (or root) addressed by `path`
1795
1796        :param str key: The unique key of the folio
1797        :param list[FolioItemModel] items: The items to add - each item's `kind` selects its shape
1798        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1799            addresses the root.
1800        """
1801        pass
1802
1803    @abstractmethod
1804    def delete_items(self, key: str, item_names: list[str], path: Optional[str] = None, cascade: bool = False) -> None:
1805        """ Delete one or more named items from the section (or root) addressed by `path`
1806
1807        :param str key: The unique key of the folio
1808        :param list[str] item_names: The names of the items to delete
1809        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1810            addresses the root.
1811        :param bool cascade: If True, and an item is an owned reference (Activity/DataStream/
1812            Folio), also delete the referenced entity
1813        """
1814        pass
1815
1816    @abstractmethod
1817    def update_item(self, key: str, item_name: str, item: FolioItemModel, path: Optional[str] = None) -> None:
1818        """ Replace a named item in the section (or root) addressed by `path`
1819
1820        :param str key: The unique key of the folio
1821        :param str item_name: The name of the item to replace
1822        :param FolioItemModel item: The item's replacement definition - `kind` selects its shape
1823        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1824            addresses the root.
1825        """
1826        pass
1827
1828    @abstractmethod
1829    def delete_item(self, key: str, item_name: str, path: Optional[str] = None, cascade: bool = False) -> None:
1830        """ Delete a single named item from the section (or root) addressed by `path`
1831
1832        :param str key: The unique key of the folio
1833        :param str item_name: The name of the item to delete
1834        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1835            addresses the root.
1836        :param bool cascade: If True, and the item is an owned reference (Activity/DataStream/
1837            Folio), also delete the referenced entity
1838        """
1839        pass
1840
1841    @abstractmethod
1842    def validate_folio(self, key: str, path: Optional[str] = None) -> FolioValidationReportModel:
1843        """ Check the root or section at `path` against the folio's optional template. Never
1844        fails because the folio doesn't (yet) satisfy it - an empty `issues` list means either
1845        there's no template, or it's fully satisfied at and below `path`.
1846
1847        :param str key: The unique key of the folio
1848        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1849            addresses the root.
1850        :return: The validation report
1851        :rtype: FolioValidationReportModel
1852        """
1853        pass

Folio management: a tree-structured document attached to an account - a versioned root plus an arbitrary tree of named sections, each holding items that are either inline structured text or references to an Activity, DataStream, or another Folio.

@abstractmethod
def create_folio( self, folio: inmotion.models.FolioModel) -> inmotion.models.FolioDetailsModel:
1664    @abstractmethod
1665    def create_folio(self, folio: FolioModel) -> FolioDetailsModel:
1666        """ Create a new, top-level, account-owned folio
1667
1668        :param FolioModel folio: The definition of the folio to create. `templateYaml` may be
1669            supplied to attach a validation template, fixed for the folio's lifetime.
1670        :return: The created folio's details
1671        :rtype: FolioDetailsModel
1672        """
1673        pass

Create a new, top-level, account-owned folio

Parameters
  • FolioModel folio: The definition of the folio to create. templateYaml may be supplied to attach a validation template, fixed for the folio's lifetime.
Returns

The created folio's details

@abstractmethod
def update_folio( self, key: str, folio: inmotion.models.FolioModel) -> inmotion.models.FolioDetailsModel:
1675    @abstractmethod
1676    def update_folio(self, key: str, folio: FolioModel) -> FolioDetailsModel:
1677        """ Update a folio's own metadata (name, description, folioType). Does not touch its
1678        section tree - use the section/item methods below for that.
1679
1680        :param str key: The unique key of the folio to update
1681        :param FolioModel folio: The updated definition of the folio
1682        :return: The updated folio's details
1683        :rtype: FolioDetailsModel
1684        """
1685        pass

Update a folio's own metadata (name, description, folioType). Does not touch its section tree - use the section/item methods below for that.

Parameters
  • str key: The unique key of the folio to update
  • FolioModel folio: The updated definition of the folio
Returns

The updated folio's details

@abstractmethod
def set_folio_locked(self, key: str, locked: bool) -> inmotion.models.FolioDetailsModel:
1687    @abstractmethod
1688    def set_folio_locked(self, key: str, locked: bool) -> FolioDetailsModel:
1689        """ Lock or unlock a folio against further Contributor edits, independent of how it was
1690        created. Any Contributor (or above) may call this at any time, regardless of the folio's
1691        current locked state - unlike update_folio, this is never blocked by the folio being
1692        locked or API-created.
1693
1694        :param str key: The unique key of the folio
1695        :param bool locked: True to lock, False to unlock
1696        :return: The folio's details, with its updated locked state
1697        :rtype: FolioDetailsModel
1698        """
1699        pass

Lock or unlock a folio against further Contributor edits, independent of how it was created. Any Contributor (or above) may call this at any time, regardless of the folio's current locked state - unlike update_folio, this is never blocked by the folio being locked or API-created.

Parameters
  • str key: The unique key of the folio
  • bool locked: True to lock, False to unlock
Returns

The folio's details, with its updated locked state

@abstractmethod
def find_folio(self, key: str) -> inmotion.models.FolioDetailsModel:
1701    @abstractmethod
1702    def find_folio(self, key: str) -> FolioDetailsModel:
1703        """ Find a folio by its unique key, including its full section tree
1704
1705        :param str key: The unique key of the folio
1706        :return: The folio's details
1707        :rtype: FolioDetailsModel
1708        """
1709        pass

Find a folio by its unique key, including its full section tree

Parameters
  • str key: The unique key of the folio
Returns

The folio's details

@abstractmethod
def delete_folio(self, key: str) -> None:
1711    @abstractmethod
1712    def delete_folio(self, key: str) -> None:
1713        """ Delete a folio by its unique key, along with its entire section tree
1714
1715        :param str key: The unique key of the folio to delete
1716        """
1717        pass

Delete a folio by its unique key, along with its entire section tree

Parameters
  • str key: The unique key of the folio to delete
@abstractmethod
def find_folios( self, account_key: str, name: Optional[str] = None, folio_type: Optional[str] = None) -> list[inmotion.models.FolioSummaryModel]:
1719    @abstractmethod
1720    def find_folios(self, account_key: str, name: Optional[str] = None, folio_type: Optional[str] = None) -> list[FolioSummaryModel]:
1721        """ List folio summaries for an account, optionally filtered by name and/or folio type
1722
1723        :param str account_key: The unique key of the account
1724        :param Optional[str] name: An optional name to filter by
1725        :param Optional[str] folio_type: An optional folio type to filter by
1726        :return: The matching folio summaries
1727        :rtype: list[FolioSummaryModel]
1728        """
1729        pass

List folio summaries for an account, optionally filtered by name and/or folio type

Parameters
  • str account_key: The unique key of the account
  • Optional[str] name: An optional name to filter by
  • Optional[str] folio_type: An optional folio type to filter by
Returns

The matching folio summaries

@abstractmethod
def find_folios_by_reference( self, account_key: str, ref_key: str) -> list[inmotion.models.FolioSummaryModel]:
1731    @abstractmethod
1732    def find_folios_by_reference(self, account_key: str, ref_key: str) -> list[FolioSummaryModel]:
1733        """ List folio summaries for an account that contain at least one item (Activity,
1734        DataStream, or Folio reference) pointing at the given key
1735
1736        :param str account_key: The unique key of the account
1737        :param str ref_key: The key of the referenced Activity, DataStream, or Folio
1738        :return: The matching folio summaries
1739        :rtype: list[FolioSummaryModel]
1740        """
1741        pass

List folio summaries for an account that contain at least one item (Activity, DataStream, or Folio reference) pointing at the given key

Parameters
  • str account_key: The unique key of the account
  • str ref_key: The key of the referenced Activity, DataStream, or Folio
Returns

The matching folio summaries

@abstractmethod
def find_section( self, key: str, path: Optional[str] = None, deep: bool = False) -> inmotion.models.FolioRootModel | inmotion.models.FolioSectionModel:
1743    @abstractmethod
1744    def find_section(self, key: str, path: Optional[str] = None, deep: bool = False) -> FolioRootModel | FolioSectionModel:
1745        """ Find the root or a named section of a folio's tree, addressed by `path`
1746
1747        :param str key: The unique key of the folio
1748        :param Optional[str] path: "/"-separated section path from the root, e.g.
1749            "Eye Tests/2026-08-04". Omitted or empty addresses the root.
1750        :param bool deep: If True, include the full subtree beneath the addressed section, not
1751            just its immediate children
1752        :return: The root (if `path` addresses it) or the section at `path`
1753        :rtype: FolioRootModel | FolioSectionModel
1754        """
1755        pass

Find the root or a named section of a folio's tree, addressed by path

Parameters
  • str key: The unique key of the folio
  • Optional[str] path: "/"-separated section path from the root, e.g. "Eye Tests/2026-08-04". Omitted or empty addresses the root.
  • bool deep: If True, include the full subtree beneath the addressed section, not just its immediate children
Returns

The root (if path addresses it) or the section at path

@abstractmethod
def create_section( self, key: str, section: inmotion.models.FolioSectionCreateModel, path: Optional[str] = None) -> None:
1757    @abstractmethod
1758    def create_section(self, key: str, section: FolioSectionCreateModel, path: Optional[str] = None) -> None:
1759        """ Add a new named section as a child of the section (or root) addressed by `path`
1760
1761        :param str key: The unique key of the folio
1762        :param FolioSectionCreateModel section: The definition of the section to create
1763        :param Optional[str] path: "/"-separated parent section path from the root. Omitted or
1764            empty adds the new section directly beneath the root.
1765        """
1766        pass

Add a new named section as a child of the section (or root) addressed by path

Parameters
  • str key: The unique key of the folio
  • FolioSectionCreateModel section: The definition of the section to create
  • Optional[str] path: "/"-separated parent section path from the root. Omitted or empty adds the new section directly beneath the root.
@abstractmethod
def update_section( self, key: str, section: inmotion.models.FolioSectionUpdateModel, path: Optional[str] = None) -> None:
1768    @abstractmethod
1769    def update_section(self, key: str, section: FolioSectionUpdateModel, path: Optional[str] = None) -> None:
1770        """ Update the section (or root) addressed by `path`. Only the fields supplied on
1771        `section` change; omitted fields are left as-is.
1772
1773        :param str key: The unique key of the folio
1774        :param FolioSectionUpdateModel section: The fields to update
1775        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1776            addresses the root.
1777        """
1778        pass

Update the section (or root) addressed by path. Only the fields supplied on section change; omitted fields are left as-is.

Parameters
  • str key: The unique key of the folio
  • FolioSectionUpdateModel section: The fields to update
  • Optional[str] path: "/"-separated section path from the root. Omitted or empty addresses the root.
@abstractmethod
def delete_section( self, key: str, path: Optional[str] = None, cascade: bool = False) -> None:
1780    @abstractmethod
1781    def delete_section(self, key: str, path: Optional[str] = None, cascade: bool = False) -> None:
1782        """ Delete the section addressed by `path` (the root itself cannot be deleted this way -
1783        use delete_folio instead)
1784
1785        :param str key: The unique key of the folio
1786        :param Optional[str] path: "/"-separated section path from the root
1787        :param bool cascade: If True, delete the section's contents (sub-sections and items)
1788            along with it - otherwise fails if the section has children
1789        """
1790        pass

Delete the section addressed by path (the root itself cannot be deleted this way - use delete_folio instead)

Parameters
  • str key: The unique key of the folio
  • Optional[str] path: "/"-separated section path from the root
  • bool cascade: If True, delete the section's contents (sub-sections and items) along with it - otherwise fails if the section has children
@abstractmethod
def add_items( self, key: str, items: list[inmotion.models.FolioItemModel], path: Optional[str] = None) -> None:
1792    @abstractmethod
1793    def add_items(self, key: str, items: list[FolioItemModel], path: Optional[str] = None) -> None:
1794        """ Add one or more items to the section (or root) addressed by `path`
1795
1796        :param str key: The unique key of the folio
1797        :param list[FolioItemModel] items: The items to add - each item's `kind` selects its shape
1798        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1799            addresses the root.
1800        """
1801        pass

Add one or more items to the section (or root) addressed by path

Parameters
  • str key: The unique key of the folio
  • list[FolioItemModel] items: The items to add - each item's kind selects its shape
  • Optional[str] path: "/"-separated section path from the root. Omitted or empty addresses the root.
@abstractmethod
def delete_items( self, key: str, item_names: list[str], path: Optional[str] = None, cascade: bool = False) -> None:
1803    @abstractmethod
1804    def delete_items(self, key: str, item_names: list[str], path: Optional[str] = None, cascade: bool = False) -> None:
1805        """ Delete one or more named items from the section (or root) addressed by `path`
1806
1807        :param str key: The unique key of the folio
1808        :param list[str] item_names: The names of the items to delete
1809        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1810            addresses the root.
1811        :param bool cascade: If True, and an item is an owned reference (Activity/DataStream/
1812            Folio), also delete the referenced entity
1813        """
1814        pass

Delete one or more named items from the section (or root) addressed by path

Parameters
  • str key: The unique key of the folio
  • list[str] item_names: The names of the items to delete
  • Optional[str] path: "/"-separated section path from the root. Omitted or empty addresses the root.
  • bool cascade: If True, and an item is an owned reference (Activity/DataStream/ Folio), also delete the referenced entity
@abstractmethod
def update_item( self, key: str, item_name: str, item: inmotion.models.FolioItemModel, path: Optional[str] = None) -> None:
1816    @abstractmethod
1817    def update_item(self, key: str, item_name: str, item: FolioItemModel, path: Optional[str] = None) -> None:
1818        """ Replace a named item in the section (or root) addressed by `path`
1819
1820        :param str key: The unique key of the folio
1821        :param str item_name: The name of the item to replace
1822        :param FolioItemModel item: The item's replacement definition - `kind` selects its shape
1823        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1824            addresses the root.
1825        """
1826        pass

Replace a named item in the section (or root) addressed by path

Parameters
  • str key: The unique key of the folio
  • str item_name: The name of the item to replace
  • FolioItemModel item: The item's replacement definition - kind selects its shape
  • Optional[str] path: "/"-separated section path from the root. Omitted or empty addresses the root.
@abstractmethod
def delete_item( self, key: str, item_name: str, path: Optional[str] = None, cascade: bool = False) -> None:
1828    @abstractmethod
1829    def delete_item(self, key: str, item_name: str, path: Optional[str] = None, cascade: bool = False) -> None:
1830        """ Delete a single named item from the section (or root) addressed by `path`
1831
1832        :param str key: The unique key of the folio
1833        :param str item_name: The name of the item to delete
1834        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1835            addresses the root.
1836        :param bool cascade: If True, and the item is an owned reference (Activity/DataStream/
1837            Folio), also delete the referenced entity
1838        """
1839        pass

Delete a single named item from the section (or root) addressed by path

Parameters
  • str key: The unique key of the folio
  • str item_name: The name of the item to delete
  • Optional[str] path: "/"-separated section path from the root. Omitted or empty addresses the root.
  • bool cascade: If True, and the item is an owned reference (Activity/DataStream/ Folio), also delete the referenced entity
@abstractmethod
def validate_folio( self, key: str, path: Optional[str] = None) -> inmotion.models.FolioValidationReportModel:
1841    @abstractmethod
1842    def validate_folio(self, key: str, path: Optional[str] = None) -> FolioValidationReportModel:
1843        """ Check the root or section at `path` against the folio's optional template. Never
1844        fails because the folio doesn't (yet) satisfy it - an empty `issues` list means either
1845        there's no template, or it's fully satisfied at and below `path`.
1846
1847        :param str key: The unique key of the folio
1848        :param Optional[str] path: "/"-separated section path from the root. Omitted or empty
1849            addresses the root.
1850        :return: The validation report
1851        :rtype: FolioValidationReportModel
1852        """
1853        pass

Check the root or section at path against the folio's optional template. Never fails because the folio doesn't (yet) satisfy it - an empty issues list means either there's no template, or it's fully satisfied at and below path.

Parameters
  • str key: The unique key of the folio
  • Optional[str] path: "/"-separated section path from the root. Omitted or empty addresses the root.
Returns

The validation report

class InMotionModel(abc.ABC):
2412class InMotionModel(ABC):
2413    """ Model catalogue: the models (equipment/sensor taxonomies) visible to or activated by an
2414    account, their node trees, and the tagging of data streams against tree nodes.
2415
2416    ``select_model``/``deselect_model``/``tag_stream``/``untag_stream`` return a raw ``dict``
2417    (e.g. ``{"selected": True}``) rather than a typed model, since the server returns an ad hoc
2418    acknowledgement object with no declared schema. """
2419
2420    @abstractmethod
2421    def find_visible_models(self, account_key: str) -> list[ModelSummaryModel]:
2422        """ List the models visible to an account
2423
2424        :param str account_key: The unique key of the account
2425        :return: Summaries of the visible models
2426        :rtype: list[ModelSummaryModel]
2427        """
2428        pass
2429
2430    @abstractmethod
2431    def find_selected_models(self, account_key: str) -> list[ModelSummaryModel]:
2432        """ List the models an account has activated
2433
2434        :param str account_key: The unique key of the account
2435        :return: Summaries of the activated models
2436        :rtype: list[ModelSummaryModel]
2437        """
2438        pass
2439
2440    @abstractmethod
2441    def find_model_tree(self, key: str, account_key: str) -> ModelTreeModel:
2442        """ Find a model's node tree
2443
2444        :param str key: The unique key of the model
2445        :param str account_key: The unique key of the account
2446        :return: The model's summary and its tree of nodes
2447        :rtype: ModelTreeModel
2448        """
2449        pass
2450
2451    @abstractmethod
2452    def select_model(self, key: str, account_key: str) -> dict:
2453        """ Activate a model for an account
2454
2455        :param str key: The unique key of the model
2456        :param str account_key: The unique key of the account
2457        :return: A raw dict acknowledging the selection, e.g. {"selected": True}
2458        :rtype: dict
2459        """
2460        pass
2461
2462    @abstractmethod
2463    def deselect_model(self, key: str, account_key: str) -> dict:
2464        """ Deactivate a model for an account
2465
2466        :param str key: The unique key of the model
2467        :param str account_key: The unique key of the account
2468        :return: A raw dict acknowledging the deselection, e.g. {"selected": False}
2469        :rtype: dict
2470        """
2471        pass
2472
2473    @abstractmethod
2474    def find_streams_for_node(self, key: str, account_key: str, path: Optional[str] = None) -> list[str]:
2475        """ Find the data stream keys tagged at a model tree node
2476
2477        :param str key: The unique key of the model
2478        :param str account_key: The unique key of the account
2479        :param Optional[str] path: An optional path to a specific node within the tree
2480        :return: The matching data stream keys
2481        :rtype: list[str]
2482        """
2483        pass
2484
2485    @abstractmethod
2486    def find_tags_for_stream(self, data_stream_key: str) -> list[StreamTagModel]:
2487        """ Find the model tree tags applied to a data stream
2488
2489        :param str data_stream_key: The unique key of the data stream
2490        :return: The matching tags
2491        :rtype: list[StreamTagModel]
2492        """
2493        pass
2494
2495    @abstractmethod
2496    def find_tags_for_account(self, account_key: str) -> list[StreamTagModel]:
2497        """ Find every model tree tag an account has made
2498
2499        :param str account_key: The unique key of the account
2500        :return: The matching tags
2501        :rtype: list[StreamTagModel]
2502        """
2503        pass
2504
2505    @abstractmethod
2506    def tag_stream(self, data_stream_key: str, account_key: str, tag: StreamTagRequestModel) -> dict:
2507        """ Tag a data stream against a model tree node
2508
2509        :param str data_stream_key: The unique key of the data stream
2510        :param str account_key: The unique key of the account
2511        :param StreamTagRequestModel tag: The model and node path to tag against
2512        :return: A raw dict acknowledging the tag, e.g. {"tagged": True}
2513        :rtype: dict
2514        """
2515        pass
2516
2517    @abstractmethod
2518    def untag_stream(self, data_stream_key: str, account_key: str, tag: StreamTagRequestModel) -> dict:
2519        """ Remove a tag from a data stream
2520
2521        :param str data_stream_key: The unique key of the data stream
2522        :param str account_key: The unique key of the account
2523        :param StreamTagRequestModel tag: The model and node path to untag
2524        :return: A raw dict acknowledging the untag, e.g. {"tagged": False}
2525        :rtype: dict
2526        """
2527        pass

Model catalogue: the models (equipment/sensor taxonomies) visible to or activated by an account, their node trees, and the tagging of data streams against tree nodes.

select_model/deselect_model/tag_stream/untag_stream return a raw dict (e.g. {"selected": True}) rather than a typed model, since the server returns an ad hoc acknowledgement object with no declared schema.

@abstractmethod
def find_visible_models(self, account_key: str) -> list[inmotion.models.ModelSummaryModel]:
2420    @abstractmethod
2421    def find_visible_models(self, account_key: str) -> list[ModelSummaryModel]:
2422        """ List the models visible to an account
2423
2424        :param str account_key: The unique key of the account
2425        :return: Summaries of the visible models
2426        :rtype: list[ModelSummaryModel]
2427        """
2428        pass

List the models visible to an account

Parameters
  • str account_key: The unique key of the account
Returns

Summaries of the visible models

@abstractmethod
def find_selected_models(self, account_key: str) -> list[inmotion.models.ModelSummaryModel]:
2430    @abstractmethod
2431    def find_selected_models(self, account_key: str) -> list[ModelSummaryModel]:
2432        """ List the models an account has activated
2433
2434        :param str account_key: The unique key of the account
2435        :return: Summaries of the activated models
2436        :rtype: list[ModelSummaryModel]
2437        """
2438        pass

List the models an account has activated

Parameters
  • str account_key: The unique key of the account
Returns

Summaries of the activated models

@abstractmethod
def find_model_tree(self, key: str, account_key: str) -> inmotion.models.ModelTreeModel:
2440    @abstractmethod
2441    def find_model_tree(self, key: str, account_key: str) -> ModelTreeModel:
2442        """ Find a model's node tree
2443
2444        :param str key: The unique key of the model
2445        :param str account_key: The unique key of the account
2446        :return: The model's summary and its tree of nodes
2447        :rtype: ModelTreeModel
2448        """
2449        pass

Find a model's node tree

Parameters
  • str key: The unique key of the model
  • str account_key: The unique key of the account
Returns

The model's summary and its tree of nodes

@abstractmethod
def select_model(self, key: str, account_key: str) -> dict:
2451    @abstractmethod
2452    def select_model(self, key: str, account_key: str) -> dict:
2453        """ Activate a model for an account
2454
2455        :param str key: The unique key of the model
2456        :param str account_key: The unique key of the account
2457        :return: A raw dict acknowledging the selection, e.g. {"selected": True}
2458        :rtype: dict
2459        """
2460        pass

Activate a model for an account

Parameters
  • str key: The unique key of the model
  • str account_key: The unique key of the account
Returns

A raw dict acknowledging the selection, e.g. {"selected": True}

@abstractmethod
def deselect_model(self, key: str, account_key: str) -> dict:
2462    @abstractmethod
2463    def deselect_model(self, key: str, account_key: str) -> dict:
2464        """ Deactivate a model for an account
2465
2466        :param str key: The unique key of the model
2467        :param str account_key: The unique key of the account
2468        :return: A raw dict acknowledging the deselection, e.g. {"selected": False}
2469        :rtype: dict
2470        """
2471        pass

Deactivate a model for an account

Parameters
  • str key: The unique key of the model
  • str account_key: The unique key of the account
Returns

A raw dict acknowledging the deselection, e.g. {"selected": False}

@abstractmethod
def find_streams_for_node( self, key: str, account_key: str, path: Optional[str] = None) -> list[str]:
2473    @abstractmethod
2474    def find_streams_for_node(self, key: str, account_key: str, path: Optional[str] = None) -> list[str]:
2475        """ Find the data stream keys tagged at a model tree node
2476
2477        :param str key: The unique key of the model
2478        :param str account_key: The unique key of the account
2479        :param Optional[str] path: An optional path to a specific node within the tree
2480        :return: The matching data stream keys
2481        :rtype: list[str]
2482        """
2483        pass

Find the data stream keys tagged at a model tree node

Parameters
  • str key: The unique key of the model
  • str account_key: The unique key of the account
  • Optional[str] path: An optional path to a specific node within the tree
Returns

The matching data stream keys

@abstractmethod
def find_tags_for_stream(self, data_stream_key: str) -> list[inmotion.models.StreamTagModel]:
2485    @abstractmethod
2486    def find_tags_for_stream(self, data_stream_key: str) -> list[StreamTagModel]:
2487        """ Find the model tree tags applied to a data stream
2488
2489        :param str data_stream_key: The unique key of the data stream
2490        :return: The matching tags
2491        :rtype: list[StreamTagModel]
2492        """
2493        pass

Find the model tree tags applied to a data stream

Parameters
  • str data_stream_key: The unique key of the data stream
Returns

The matching tags

@abstractmethod
def find_tags_for_account(self, account_key: str) -> list[inmotion.models.StreamTagModel]:
2495    @abstractmethod
2496    def find_tags_for_account(self, account_key: str) -> list[StreamTagModel]:
2497        """ Find every model tree tag an account has made
2498
2499        :param str account_key: The unique key of the account
2500        :return: The matching tags
2501        :rtype: list[StreamTagModel]
2502        """
2503        pass

Find every model tree tag an account has made

Parameters
  • str account_key: The unique key of the account
Returns

The matching tags

@abstractmethod
def tag_stream( self, data_stream_key: str, account_key: str, tag: inmotion.models.StreamTagRequestModel) -> dict:
2505    @abstractmethod
2506    def tag_stream(self, data_stream_key: str, account_key: str, tag: StreamTagRequestModel) -> dict:
2507        """ Tag a data stream against a model tree node
2508
2509        :param str data_stream_key: The unique key of the data stream
2510        :param str account_key: The unique key of the account
2511        :param StreamTagRequestModel tag: The model and node path to tag against
2512        :return: A raw dict acknowledging the tag, e.g. {"tagged": True}
2513        :rtype: dict
2514        """
2515        pass

Tag a data stream against a model tree node

Parameters
  • str data_stream_key: The unique key of the data stream
  • str account_key: The unique key of the account
  • StreamTagRequestModel tag: The model and node path to tag against
Returns

A raw dict acknowledging the tag, e.g. {"tagged": True}

@abstractmethod
def untag_stream( self, data_stream_key: str, account_key: str, tag: inmotion.models.StreamTagRequestModel) -> dict:
2517    @abstractmethod
2518    def untag_stream(self, data_stream_key: str, account_key: str, tag: StreamTagRequestModel) -> dict:
2519        """ Remove a tag from a data stream
2520
2521        :param str data_stream_key: The unique key of the data stream
2522        :param str account_key: The unique key of the account
2523        :param StreamTagRequestModel tag: The model and node path to untag
2524        :return: A raw dict acknowledging the untag, e.g. {"tagged": False}
2525        :rtype: dict
2526        """
2527        pass

Remove a tag from a data stream

Parameters
  • str data_stream_key: The unique key of the data stream
  • str account_key: The unique key of the account
  • StreamTagRequestModel tag: The model and node path to untag
Returns

A raw dict acknowledging the untag, e.g. {"tagged": False}

class InMotionMqttDeployment(abc.ABC):
2319class InMotionMqttDeployment(ABC):
2320    """ MQTT ingestion deployments: a `type: mqtt` (schema-v2) Device Config is the *class*;
2321    registering a deployment against a published version of it is what creates the backing Site
2322    activity (sensor schema from the config's `variables:` block) and mints the scoped,
2323    publish-only API key the device authenticates to the broker with.
2324
2325    Every method is admin-gated on the account. The scoped key value is returned exactly once, in
2326    the register / rotate-key response - it is not recoverable afterwards. Responses have no fixed
2327    schema, so each method returns a raw ``dict`` (or ``list[dict]``). """
2328
2329    @abstractmethod
2330    def register_mqtt_deployment(self, account_key: str, registration: MqttDeploymentRegistrationModel) -> dict:
2331        """ Register a deployment against a published `type: mqtt` device-config. Creates a Site
2332        activity from the config's `variables:` block, mints a scoped publish-only key, and
2333        returns ``{deploymentId, apiKey, keyName, keyExpiryOn, topicPrefix, brokerHost,
2334        activityKey, deviceConfigName, deviceConfigVersion, deviceConfigSemanticVersion}``. The
2335        ``apiKey`` is shown only in this response.
2336
2337        :param str account_key: The unique key of the account
2338        :param MqttDeploymentRegistrationModel registration: The deployment to register
2339        :return: The registered deployment, including its one-time publish key
2340        :rtype: dict
2341        """
2342        pass
2343
2344    @abstractmethod
2345    def list_mqtt_deployments(self, account_key: str) -> dict:
2346        """ List the account's MQTT ingestion deployments as ``{"deployments": [...]}``. Each row
2347        carries ``activityExists`` - False (or None if it could not be checked) means the backing
2348        Site activity has been deleted and the deployment must be re-registered.
2349
2350        :param str account_key: The unique key of the account
2351        :return: ``{"deployments": [...]}``
2352        :rtype: dict
2353        """
2354        pass
2355
2356    @abstractmethod
2357    def update_mqtt_deployment(self, account_key: str, deployment_id: str, update: MqttDeploymentUpdateModel) -> dict:
2358        """ Update mutable properties of a deployment (currently only ``name``). The backing Site
2359        activity is not renamed.
2360
2361        :param str account_key: The unique key of the account
2362        :param str deployment_id: The deployment's id
2363        :param MqttDeploymentUpdateModel update: The fields to change
2364        :return: ``{deploymentId, name}``
2365        :rtype: dict
2366        """
2367        pass
2368
2369    @abstractmethod
2370    def delete_mqtt_deployment(self, account_key: str, deployment_id: str) -> dict:
2371        """ Remove the deployment row and revoke its scoped publish key. The backing Site activity
2372        is left in place (archival is a separate action); the response reports
2373        ``{deploymentId, activityKey, activityRetained}``.
2374
2375        :param str account_key: The unique key of the account
2376        :param str deployment_id: The deployment's id
2377        :return: ``{deploymentId, activityKey, activityRetained}``
2378        :rtype: dict
2379        """
2380        pass
2381
2382    @abstractmethod
2383    def repoint_mqtt_deployment(self, account_key: str, deployment_id: str) -> dict:
2384        """ Move the deployment to the account's newest published version of the same
2385        device-config so the subscriber picks up its new decode/routing/scaling rules. The
2386        backing activity's variable set is fixed, so any variables a newer version adds come back
2387        in ``unmappedVariables``. Idempotent - returns ``changed=False`` when already current.
2388
2389        :param str account_key: The unique key of the account
2390        :param str deployment_id: The deployment's id
2391        :return: The re-point outcome (``changed`` plus version details, and ``unmappedVariables``
2392            when it moved)
2393        :rtype: dict
2394        """
2395        pass
2396
2397    @abstractmethod
2398    def rotate_mqtt_deployment_key(self, account_key: str, deployment_id: str) -> dict:
2399        """ Mint a fresh publish-only key and revoke the old one, for a lost or compromised
2400        credential. The ``deploymentId``, ``topicPrefix`` and backing activity are unchanged; the
2401        new key is returned once (``{deploymentId, apiKey, topicPrefix, brokerHost}``) and any
2402        live broker session on the old key is force-disconnected.
2403
2404        :param str account_key: The unique key of the account
2405        :param str deployment_id: The deployment's id
2406        :return: ``{deploymentId, apiKey, topicPrefix, brokerHost}``
2407        :rtype: dict
2408        """
2409        pass

MQTT ingestion deployments: a type: mqtt (schema-v2) Device Config is the class; registering a deployment against a published version of it is what creates the backing Site activity (sensor schema from the config's variables: block) and mints the scoped, publish-only API key the device authenticates to the broker with.

Every method is admin-gated on the account. The scoped key value is returned exactly once, in the register / rotate-key response - it is not recoverable afterwards. Responses have no fixed schema, so each method returns a raw dict (or list[dict]).

@abstractmethod
def register_mqtt_deployment( self, account_key: str, registration: inmotion.models.MqttDeploymentRegistrationModel) -> dict:
2329    @abstractmethod
2330    def register_mqtt_deployment(self, account_key: str, registration: MqttDeploymentRegistrationModel) -> dict:
2331        """ Register a deployment against a published `type: mqtt` device-config. Creates a Site
2332        activity from the config's `variables:` block, mints a scoped publish-only key, and
2333        returns ``{deploymentId, apiKey, keyName, keyExpiryOn, topicPrefix, brokerHost,
2334        activityKey, deviceConfigName, deviceConfigVersion, deviceConfigSemanticVersion}``. The
2335        ``apiKey`` is shown only in this response.
2336
2337        :param str account_key: The unique key of the account
2338        :param MqttDeploymentRegistrationModel registration: The deployment to register
2339        :return: The registered deployment, including its one-time publish key
2340        :rtype: dict
2341        """
2342        pass

Register a deployment against a published type: mqtt device-config. Creates a Site activity from the config's variables: block, mints a scoped publish-only key, and returns {deploymentId, apiKey, keyName, keyExpiryOn, topicPrefix, brokerHost, activityKey, deviceConfigName, deviceConfigVersion, deviceConfigSemanticVersion}. The apiKey is shown only in this response.

Parameters
  • str account_key: The unique key of the account
  • MqttDeploymentRegistrationModel registration: The deployment to register
Returns

The registered deployment, including its one-time publish key

@abstractmethod
def list_mqtt_deployments(self, account_key: str) -> dict:
2344    @abstractmethod
2345    def list_mqtt_deployments(self, account_key: str) -> dict:
2346        """ List the account's MQTT ingestion deployments as ``{"deployments": [...]}``. Each row
2347        carries ``activityExists`` - False (or None if it could not be checked) means the backing
2348        Site activity has been deleted and the deployment must be re-registered.
2349
2350        :param str account_key: The unique key of the account
2351        :return: ``{"deployments": [...]}``
2352        :rtype: dict
2353        """
2354        pass

List the account's MQTT ingestion deployments as {"deployments": [...]}. Each row carries activityExists - False (or None if it could not be checked) means the backing Site activity has been deleted and the deployment must be re-registered.

Parameters
  • str account_key: The unique key of the account
Returns

{"deployments": [...]}

@abstractmethod
def update_mqtt_deployment( self, account_key: str, deployment_id: str, update: inmotion.models.MqttDeploymentUpdateModel) -> dict:
2356    @abstractmethod
2357    def update_mqtt_deployment(self, account_key: str, deployment_id: str, update: MqttDeploymentUpdateModel) -> dict:
2358        """ Update mutable properties of a deployment (currently only ``name``). The backing Site
2359        activity is not renamed.
2360
2361        :param str account_key: The unique key of the account
2362        :param str deployment_id: The deployment's id
2363        :param MqttDeploymentUpdateModel update: The fields to change
2364        :return: ``{deploymentId, name}``
2365        :rtype: dict
2366        """
2367        pass

Update mutable properties of a deployment (currently only name). The backing Site activity is not renamed.

Parameters
  • str account_key: The unique key of the account
  • str deployment_id: The deployment's id
  • MqttDeploymentUpdateModel update: The fields to change
Returns

{deploymentId, name}

@abstractmethod
def delete_mqtt_deployment(self, account_key: str, deployment_id: str) -> dict:
2369    @abstractmethod
2370    def delete_mqtt_deployment(self, account_key: str, deployment_id: str) -> dict:
2371        """ Remove the deployment row and revoke its scoped publish key. The backing Site activity
2372        is left in place (archival is a separate action); the response reports
2373        ``{deploymentId, activityKey, activityRetained}``.
2374
2375        :param str account_key: The unique key of the account
2376        :param str deployment_id: The deployment's id
2377        :return: ``{deploymentId, activityKey, activityRetained}``
2378        :rtype: dict
2379        """
2380        pass

Remove the deployment row and revoke its scoped publish key. The backing Site activity is left in place (archival is a separate action); the response reports {deploymentId, activityKey, activityRetained}.

Parameters
  • str account_key: The unique key of the account
  • str deployment_id: The deployment's id
Returns

{deploymentId, activityKey, activityRetained}

@abstractmethod
def repoint_mqtt_deployment(self, account_key: str, deployment_id: str) -> dict:
2382    @abstractmethod
2383    def repoint_mqtt_deployment(self, account_key: str, deployment_id: str) -> dict:
2384        """ Move the deployment to the account's newest published version of the same
2385        device-config so the subscriber picks up its new decode/routing/scaling rules. The
2386        backing activity's variable set is fixed, so any variables a newer version adds come back
2387        in ``unmappedVariables``. Idempotent - returns ``changed=False`` when already current.
2388
2389        :param str account_key: The unique key of the account
2390        :param str deployment_id: The deployment's id
2391        :return: The re-point outcome (``changed`` plus version details, and ``unmappedVariables``
2392            when it moved)
2393        :rtype: dict
2394        """
2395        pass

Move the deployment to the account's newest published version of the same device-config so the subscriber picks up its new decode/routing/scaling rules. The backing activity's variable set is fixed, so any variables a newer version adds come back in unmappedVariables. Idempotent - returns changed=False when already current.

Parameters
  • str account_key: The unique key of the account
  • str deployment_id: The deployment's id
Returns

The re-point outcome (changed plus version details, and unmappedVariables when it moved)

@abstractmethod
def rotate_mqtt_deployment_key(self, account_key: str, deployment_id: str) -> dict:
2397    @abstractmethod
2398    def rotate_mqtt_deployment_key(self, account_key: str, deployment_id: str) -> dict:
2399        """ Mint a fresh publish-only key and revoke the old one, for a lost or compromised
2400        credential. The ``deploymentId``, ``topicPrefix`` and backing activity are unchanged; the
2401        new key is returned once (``{deploymentId, apiKey, topicPrefix, brokerHost}``) and any
2402        live broker session on the old key is force-disconnected.
2403
2404        :param str account_key: The unique key of the account
2405        :param str deployment_id: The deployment's id
2406        :return: ``{deploymentId, apiKey, topicPrefix, brokerHost}``
2407        :rtype: dict
2408        """
2409        pass

Mint a fresh publish-only key and revoke the old one, for a lost or compromised credential. The deploymentId, topicPrefix and backing activity are unchanged; the new key is returned once ({deploymentId, apiKey, topicPrefix, brokerHost}) and any live broker session on the old key is force-disconnected.

Parameters
  • str account_key: The unique key of the account
  • str deployment_id: The deployment's id
Returns

{deploymentId, apiKey, topicPrefix, brokerHost}

class InMotionShape(abc.ABC):
1856class InMotionShape(ABC):
1857    """ Shape management: a named, classified collection of polygons (which may have holes/
1858    islands), stored as a single GeoJSON FeatureCollection. Access is gated by a simple
1859    feature-flag check (an account write privilege plus the "shape-editor" account feature), not
1860    Folio's role/contributor model. """
1861
1862    @abstractmethod
1863    def create_shape(self, shape: ShapeModel) -> ShapeDetailsModel:
1864        """ Create a new, account-owned shape
1865
1866        :param ShapeModel shape: The definition of the shape to create
1867        :return: The created shape's details
1868        :rtype: ShapeDetailsModel
1869        """
1870        pass
1871
1872    @abstractmethod
1873    def find_shapes(self, account_key: str, classification: Optional[str] = None) -> list[ShapeSummaryModel]:
1874        """ List shape summaries for an account, optionally filtered by classification
1875
1876        :param str account_key: The unique key of the account
1877        :param Optional[str] classification: An optional classification to filter by
1878        :return: The matching shape summaries
1879        :rtype: list[ShapeSummaryModel]
1880        """
1881        pass
1882
1883    @abstractmethod
1884    def find_shape(self, key: str) -> ShapeDetailsModel:
1885        """ Find a shape by its unique key, including its full geojson and collection-level
1886        variables
1887
1888        :param str key: The unique key of the shape
1889        :return: The shape's details
1890        :rtype: ShapeDetailsModel
1891        """
1892        pass
1893
1894    @abstractmethod
1895    def update_shape(self, key: str, shape: ShapeUpdateModel) -> ShapeDetailsModel:
1896        """ Update a shape's metadata (name, classification, collection-level variables). Does
1897        not touch its geometry - use update_shape_geometry for that.
1898
1899        :param str key: The unique key of the shape to update
1900        :param ShapeUpdateModel shape: The fields to update
1901        :return: The updated shape's details
1902        :rtype: ShapeDetailsModel
1903        """
1904        pass
1905
1906    @abstractmethod
1907    def update_shape_geometry(self, key: str, geometry: ShapeGeometryModel) -> ShapeDetailsModel:
1908        """ Replace a shape's geojson only
1909
1910        :param str key: The unique key of the shape to update
1911        :param ShapeGeometryModel geometry: The replacement geojson
1912        :return: The updated shape's details
1913        :rtype: ShapeDetailsModel
1914        """
1915        pass
1916
1917    @abstractmethod
1918    def duplicate_shape(self, key: str) -> ShapeDetailsModel:
1919        """ Copy an existing shape's geometry and metadata into a new, independent shape owned by
1920        the caller.
1921
1922        :param str key: The unique key of the shape to duplicate
1923        :return: The new, duplicated shape's details
1924        :rtype: ShapeDetailsModel
1925        """
1926        pass
1927
1928    @abstractmethod
1929    def delete_shape(self, key: str) -> None:
1930        """ Delete a shape by its unique key
1931
1932        :param str key: The unique key of the shape to delete
1933        """
1934        pass
1935
1936    @abstractmethod
1937    def find_model_field_groups(self, key: str) -> list[ModelFieldGroupModel]:
1938        """ Find a shape's custom classification field values - one field group per active
1939        classification tag on this shape.
1940
1941        :param str key: The unique key of the shape
1942        :return: The shape's active classification field groups
1943        :rtype: list[ModelFieldGroupModel]
1944        """
1945        pass
1946
1947    @abstractmethod
1948    def set_model_field_value(self, key: str, request: SetModelFieldValueRequestModel) -> list[ModelFieldGroupModel]:
1949        """ Set (or, if value is omitted/blank on an optional field, clear) one custom
1950        classification field's value for one active tag on a shape.
1951
1952        :param str key: The unique key of the shape
1953        :param SetModelFieldValueRequestModel request: The field value to set
1954        :return: The shape's active classification field groups, including the updated value
1955        :rtype: list[ModelFieldGroupModel]
1956        """
1957        pass

Shape management: a named, classified collection of polygons (which may have holes/ islands), stored as a single GeoJSON FeatureCollection. Access is gated by a simple feature-flag check (an account write privilege plus the "shape-editor" account feature), not Folio's role/contributor model.

@abstractmethod
def create_shape( self, shape: inmotion.models.ShapeModel) -> inmotion.models.ShapeDetailsModel:
1862    @abstractmethod
1863    def create_shape(self, shape: ShapeModel) -> ShapeDetailsModel:
1864        """ Create a new, account-owned shape
1865
1866        :param ShapeModel shape: The definition of the shape to create
1867        :return: The created shape's details
1868        :rtype: ShapeDetailsModel
1869        """
1870        pass

Create a new, account-owned shape

Parameters
  • ShapeModel shape: The definition of the shape to create
Returns

The created shape's details

@abstractmethod
def find_shapes( self, account_key: str, classification: Optional[str] = None) -> list[inmotion.models.ShapeSummaryModel]:
1872    @abstractmethod
1873    def find_shapes(self, account_key: str, classification: Optional[str] = None) -> list[ShapeSummaryModel]:
1874        """ List shape summaries for an account, optionally filtered by classification
1875
1876        :param str account_key: The unique key of the account
1877        :param Optional[str] classification: An optional classification to filter by
1878        :return: The matching shape summaries
1879        :rtype: list[ShapeSummaryModel]
1880        """
1881        pass

List shape summaries for an account, optionally filtered by classification

Parameters
  • str account_key: The unique key of the account
  • Optional[str] classification: An optional classification to filter by
Returns

The matching shape summaries

@abstractmethod
def find_shape(self, key: str) -> inmotion.models.ShapeDetailsModel:
1883    @abstractmethod
1884    def find_shape(self, key: str) -> ShapeDetailsModel:
1885        """ Find a shape by its unique key, including its full geojson and collection-level
1886        variables
1887
1888        :param str key: The unique key of the shape
1889        :return: The shape's details
1890        :rtype: ShapeDetailsModel
1891        """
1892        pass

Find a shape by its unique key, including its full geojson and collection-level variables

Parameters
  • str key: The unique key of the shape
Returns

The shape's details

@abstractmethod
def update_shape( self, key: str, shape: inmotion.models.ShapeUpdateModel) -> inmotion.models.ShapeDetailsModel:
1894    @abstractmethod
1895    def update_shape(self, key: str, shape: ShapeUpdateModel) -> ShapeDetailsModel:
1896        """ Update a shape's metadata (name, classification, collection-level variables). Does
1897        not touch its geometry - use update_shape_geometry for that.
1898
1899        :param str key: The unique key of the shape to update
1900        :param ShapeUpdateModel shape: The fields to update
1901        :return: The updated shape's details
1902        :rtype: ShapeDetailsModel
1903        """
1904        pass

Update a shape's metadata (name, classification, collection-level variables). Does not touch its geometry - use update_shape_geometry for that.

Parameters
  • str key: The unique key of the shape to update
  • ShapeUpdateModel shape: The fields to update
Returns

The updated shape's details

@abstractmethod
def update_shape_geometry( self, key: str, geometry: inmotion.models.ShapeGeometryModel) -> inmotion.models.ShapeDetailsModel:
1906    @abstractmethod
1907    def update_shape_geometry(self, key: str, geometry: ShapeGeometryModel) -> ShapeDetailsModel:
1908        """ Replace a shape's geojson only
1909
1910        :param str key: The unique key of the shape to update
1911        :param ShapeGeometryModel geometry: The replacement geojson
1912        :return: The updated shape's details
1913        :rtype: ShapeDetailsModel
1914        """
1915        pass

Replace a shape's geojson only

Parameters
  • str key: The unique key of the shape to update
  • ShapeGeometryModel geometry: The replacement geojson
Returns

The updated shape's details

@abstractmethod
def duplicate_shape(self, key: str) -> inmotion.models.ShapeDetailsModel:
1917    @abstractmethod
1918    def duplicate_shape(self, key: str) -> ShapeDetailsModel:
1919        """ Copy an existing shape's geometry and metadata into a new, independent shape owned by
1920        the caller.
1921
1922        :param str key: The unique key of the shape to duplicate
1923        :return: The new, duplicated shape's details
1924        :rtype: ShapeDetailsModel
1925        """
1926        pass

Copy an existing shape's geometry and metadata into a new, independent shape owned by the caller.

Parameters
  • str key: The unique key of the shape to duplicate
Returns

The new, duplicated shape's details

@abstractmethod
def delete_shape(self, key: str) -> None:
1928    @abstractmethod
1929    def delete_shape(self, key: str) -> None:
1930        """ Delete a shape by its unique key
1931
1932        :param str key: The unique key of the shape to delete
1933        """
1934        pass

Delete a shape by its unique key

Parameters
  • str key: The unique key of the shape to delete
@abstractmethod
def find_model_field_groups(self, key: str) -> list[inmotion.models.ModelFieldGroupModel]:
1936    @abstractmethod
1937    def find_model_field_groups(self, key: str) -> list[ModelFieldGroupModel]:
1938        """ Find a shape's custom classification field values - one field group per active
1939        classification tag on this shape.
1940
1941        :param str key: The unique key of the shape
1942        :return: The shape's active classification field groups
1943        :rtype: list[ModelFieldGroupModel]
1944        """
1945        pass

Find a shape's custom classification field values - one field group per active classification tag on this shape.

Parameters
  • str key: The unique key of the shape
Returns

The shape's active classification field groups

@abstractmethod
def set_model_field_value( self, key: str, request: inmotion.models.SetModelFieldValueRequestModel) -> list[inmotion.models.ModelFieldGroupModel]:
1947    @abstractmethod
1948    def set_model_field_value(self, key: str, request: SetModelFieldValueRequestModel) -> list[ModelFieldGroupModel]:
1949        """ Set (or, if value is omitted/blank on an optional field, clear) one custom
1950        classification field's value for one active tag on a shape.
1951
1952        :param str key: The unique key of the shape
1953        :param SetModelFieldValueRequestModel request: The field value to set
1954        :return: The shape's active classification field groups, including the updated value
1955        :rtype: list[ModelFieldGroupModel]
1956        """
1957        pass

Set (or, if value is omitted/blank on an optional field, clear) one custom classification field's value for one active tag on a shape.

Parameters
  • str key: The unique key of the shape
  • SetModelFieldValueRequestModel request: The field value to set
Returns

The shape's active classification field groups, including the updated value

class InMotionShapeGenerator(abc.ABC):
2199class InMotionShapeGenerator(ABC):
2200    """ Shape generator management: a rules-based geometry generator (Shape Editor v2). Its
2201    identity is its rules (type/params), not a piece of geometry - see `commit_shape_generator`
2202    for snapshotting its output into an independent Shape. Access is gated the same way as
2203    Shape. """
2204
2205    @abstractmethod
2206    def create_shape_generator(self, generator: ShapeGeneratorModel) -> ShapeGeneratorDetailsModel:
2207        """ Create a new, account-owned shape generator
2208
2209        :param ShapeGeneratorModel generator: The definition of the shape generator to create
2210        :return: The created shape generator's details
2211        :rtype: ShapeGeneratorDetailsModel
2212        """
2213        pass
2214
2215    @abstractmethod
2216    def find_shape_generators(self, account_key: str) -> list[ShapeGeneratorSummaryModel]:
2217        """ List shape generator summaries for an account
2218
2219        :param str account_key: The unique key of the account
2220        :return: The matching shape generator summaries
2221        :rtype: list[ShapeGeneratorSummaryModel]
2222        """
2223        pass
2224
2225    @abstractmethod
2226    def find_shape_generator(self, key: str) -> ShapeGeneratorDetailsModel:
2227        """ Find a shape generator by its unique key
2228
2229        :param str key: The unique key of the shape generator
2230        :return: The shape generator's details
2231        :rtype: ShapeGeneratorDetailsModel
2232        """
2233        pass
2234
2235    @abstractmethod
2236    def update_shape_generator(self, key: str, generator: ShapeGeneratorUpdateModel) -> ShapeGeneratorDetailsModel:
2237        """ Full-replace update of a generator's rules (name/params/boundary/label prefix). Does
2238        not itself change its cached generated geometry - see regenerate_shape_generator.
2239
2240        :param str key: The unique key of the shape generator to update
2241        :param ShapeGeneratorUpdateModel generator: The replacement definition
2242        :return: The updated shape generator's details
2243        :rtype: ShapeGeneratorDetailsModel
2244        """
2245        pass
2246
2247    @abstractmethod
2248    def regenerate_shape_generator(self, key: str) -> ShapeGeneratorDetailsModel:
2249        """ Re-run the generator's pipeline against its current rules and boundary shape, and
2250        persist the result as the new cached generated geometry.
2251
2252        :param str key: The unique key of the shape generator to regenerate
2253        :return: The shape generator's details, with its refreshed cached output
2254        :rtype: ShapeGeneratorDetailsModel
2255        """
2256        pass
2257
2258    @abstractmethod
2259    def commit_shape_generator(self, key: str) -> ShapeDetailsModel:
2260        """ Snapshot the generator's cached generated geometry into a brand-new, independent
2261        shape. The generator itself keeps running/re-tunable afterwards. Fails with a 400 if
2262        nothing has been generated yet (regenerate first).
2263
2264        :param str key: The unique key of the shape generator to commit
2265        :return: The new shape created from the generator's output
2266        :rtype: ShapeDetailsModel
2267        """
2268        pass
2269
2270    @abstractmethod
2271    def preview_shape_generator(self, key: str, seed_indices: list[int]) -> dict:
2272        """ Incrementally recompute only the cells around the given seed indices and return them
2273        as a GeoJSON FeatureCollection, without touching the generator's cached
2274        `generatedGeojson`. For instant feedback on a seed drag; voronoi generators only.
2275
2276        :param str key: The unique key of the shape generator
2277        :param list[int] seed_indices: Indices of the seed points that moved
2278        :return: A GeoJSON FeatureCollection of the recomputed cells
2279        :rtype: dict
2280        """
2281        pass
2282
2283    @abstractmethod
2284    def find_nearby_tracks(self, account_key: str, track_filter: NearbyTracksFilterModel) -> list[NearbyTrackModel]:
2285        """ Find the account's Track activities whose recorded extent overlaps a bounding box -
2286        candidate input for idw/nn shape generators.
2287
2288        :param str account_key: The unique key of the account
2289        :param NearbyTracksFilterModel track_filter: The query bounding box
2290        :return: The matching Track candidates
2291        :rtype: list[NearbyTrackModel]
2292        """
2293        pass
2294
2295    @abstractmethod
2296    def delete_shape_generator(self, key: str) -> None:
2297        """ Delete a shape generator by its unique key
2298
2299        :param str key: The unique key of the shape generator to delete
2300        """
2301        pass

Shape generator management: a rules-based geometry generator (Shape Editor v2). Its identity is its rules (type/params), not a piece of geometry - see commit_shape_generator for snapshotting its output into an independent Shape. Access is gated the same way as Shape.

@abstractmethod
def create_shape_generator( self, generator: inmotion.models.ShapeGeneratorModel) -> inmotion.models.ShapeGeneratorDetailsModel:
2205    @abstractmethod
2206    def create_shape_generator(self, generator: ShapeGeneratorModel) -> ShapeGeneratorDetailsModel:
2207        """ Create a new, account-owned shape generator
2208
2209        :param ShapeGeneratorModel generator: The definition of the shape generator to create
2210        :return: The created shape generator's details
2211        :rtype: ShapeGeneratorDetailsModel
2212        """
2213        pass

Create a new, account-owned shape generator

Parameters
  • ShapeGeneratorModel generator: The definition of the shape generator to create
Returns

The created shape generator's details

@abstractmethod
def find_shape_generators( self, account_key: str) -> list[inmotion.models.ShapeGeneratorSummaryModel]:
2215    @abstractmethod
2216    def find_shape_generators(self, account_key: str) -> list[ShapeGeneratorSummaryModel]:
2217        """ List shape generator summaries for an account
2218
2219        :param str account_key: The unique key of the account
2220        :return: The matching shape generator summaries
2221        :rtype: list[ShapeGeneratorSummaryModel]
2222        """
2223        pass

List shape generator summaries for an account

Parameters
  • str account_key: The unique key of the account
Returns

The matching shape generator summaries

@abstractmethod
def find_shape_generator(self, key: str) -> inmotion.models.ShapeGeneratorDetailsModel:
2225    @abstractmethod
2226    def find_shape_generator(self, key: str) -> ShapeGeneratorDetailsModel:
2227        """ Find a shape generator by its unique key
2228
2229        :param str key: The unique key of the shape generator
2230        :return: The shape generator's details
2231        :rtype: ShapeGeneratorDetailsModel
2232        """
2233        pass

Find a shape generator by its unique key

Parameters
  • str key: The unique key of the shape generator
Returns

The shape generator's details

@abstractmethod
def update_shape_generator( self, key: str, generator: inmotion.models.ShapeGeneratorUpdateModel) -> inmotion.models.ShapeGeneratorDetailsModel:
2235    @abstractmethod
2236    def update_shape_generator(self, key: str, generator: ShapeGeneratorUpdateModel) -> ShapeGeneratorDetailsModel:
2237        """ Full-replace update of a generator's rules (name/params/boundary/label prefix). Does
2238        not itself change its cached generated geometry - see regenerate_shape_generator.
2239
2240        :param str key: The unique key of the shape generator to update
2241        :param ShapeGeneratorUpdateModel generator: The replacement definition
2242        :return: The updated shape generator's details
2243        :rtype: ShapeGeneratorDetailsModel
2244        """
2245        pass

Full-replace update of a generator's rules (name/params/boundary/label prefix). Does not itself change its cached generated geometry - see regenerate_shape_generator.

Parameters
  • str key: The unique key of the shape generator to update
  • ShapeGeneratorUpdateModel generator: The replacement definition
Returns

The updated shape generator's details

@abstractmethod
def regenerate_shape_generator(self, key: str) -> inmotion.models.ShapeGeneratorDetailsModel:
2247    @abstractmethod
2248    def regenerate_shape_generator(self, key: str) -> ShapeGeneratorDetailsModel:
2249        """ Re-run the generator's pipeline against its current rules and boundary shape, and
2250        persist the result as the new cached generated geometry.
2251
2252        :param str key: The unique key of the shape generator to regenerate
2253        :return: The shape generator's details, with its refreshed cached output
2254        :rtype: ShapeGeneratorDetailsModel
2255        """
2256        pass

Re-run the generator's pipeline against its current rules and boundary shape, and persist the result as the new cached generated geometry.

Parameters
  • str key: The unique key of the shape generator to regenerate
Returns

The shape generator's details, with its refreshed cached output

@abstractmethod
def commit_shape_generator(self, key: str) -> inmotion.models.ShapeDetailsModel:
2258    @abstractmethod
2259    def commit_shape_generator(self, key: str) -> ShapeDetailsModel:
2260        """ Snapshot the generator's cached generated geometry into a brand-new, independent
2261        shape. The generator itself keeps running/re-tunable afterwards. Fails with a 400 if
2262        nothing has been generated yet (regenerate first).
2263
2264        :param str key: The unique key of the shape generator to commit
2265        :return: The new shape created from the generator's output
2266        :rtype: ShapeDetailsModel
2267        """
2268        pass

Snapshot the generator's cached generated geometry into a brand-new, independent shape. The generator itself keeps running/re-tunable afterwards. Fails with a 400 if nothing has been generated yet (regenerate first).

Parameters
  • str key: The unique key of the shape generator to commit
Returns

The new shape created from the generator's output

@abstractmethod
def preview_shape_generator(self, key: str, seed_indices: list[int]) -> dict:
2270    @abstractmethod
2271    def preview_shape_generator(self, key: str, seed_indices: list[int]) -> dict:
2272        """ Incrementally recompute only the cells around the given seed indices and return them
2273        as a GeoJSON FeatureCollection, without touching the generator's cached
2274        `generatedGeojson`. For instant feedback on a seed drag; voronoi generators only.
2275
2276        :param str key: The unique key of the shape generator
2277        :param list[int] seed_indices: Indices of the seed points that moved
2278        :return: A GeoJSON FeatureCollection of the recomputed cells
2279        :rtype: dict
2280        """
2281        pass

Incrementally recompute only the cells around the given seed indices and return them as a GeoJSON FeatureCollection, without touching the generator's cached generatedGeojson. For instant feedback on a seed drag; voronoi generators only.

Parameters
  • str key: The unique key of the shape generator
  • list[int] seed_indices: Indices of the seed points that moved
Returns

A GeoJSON FeatureCollection of the recomputed cells

@abstractmethod
def find_nearby_tracks( self, account_key: str, track_filter: inmotion.models.NearbyTracksFilterModel) -> list[inmotion.models.NearbyTrackModel]:
2283    @abstractmethod
2284    def find_nearby_tracks(self, account_key: str, track_filter: NearbyTracksFilterModel) -> list[NearbyTrackModel]:
2285        """ Find the account's Track activities whose recorded extent overlaps a bounding box -
2286        candidate input for idw/nn shape generators.
2287
2288        :param str account_key: The unique key of the account
2289        :param NearbyTracksFilterModel track_filter: The query bounding box
2290        :return: The matching Track candidates
2291        :rtype: list[NearbyTrackModel]
2292        """
2293        pass

Find the account's Track activities whose recorded extent overlaps a bounding box - candidate input for idw/nn shape generators.

Parameters
  • str account_key: The unique key of the account
  • NearbyTracksFilterModel track_filter: The query bounding box
Returns

The matching Track candidates

@abstractmethod
def delete_shape_generator(self, key: str) -> None:
2295    @abstractmethod
2296    def delete_shape_generator(self, key: str) -> None:
2297        """ Delete a shape generator by its unique key
2298
2299        :param str key: The unique key of the shape generator to delete
2300        """
2301        pass

Delete a shape generator by its unique key

Parameters
  • str key: The unique key of the shape generator to delete
class InMotionUpload(abc.ABC):
1560class InMotionUpload(ABC):
1561    @abstractmethod
1562    def upload_file(self, account: str, file_path: str, content_type: str = 'application/octet-stream') -> dict[str, UploadMetadataModel]:
1563        """ Upload a file to the nominated account using a multipart form
1564
1565        :param str account: The unique key of the account to upload the file to
1566        :param str file_path: The path to the local file to upload
1567        :param str content_type: The MIME type to declare for the uploaded file
1568        :return: A map of the new upload's uuid to its metadata (one entry per uploaded file)
1569        :rtype: dict[str, UploadMetadataModel]
1570        """
1571        pass
1572
1573    @abstractmethod
1574    def find_upload_metadata(self, uuid: str) -> UploadMetadataModel:
1575        """ Retrieve the metadata for a specific file upload
1576
1577        :param str uuid: The unique identifier for the upload
1578        :return: The upload's metadata
1579        :rtype: UploadMetadataModel
1580        """
1581        pass
1582
1583    @abstractmethod
1584    def update_upload_metadata(self, uuid: str, change: UploadMetadataChangeCommandModel) -> dict[str, UploadMetadataModel]:
1585        """ Update the metadata (mime type, nature, attributes) for a specific file upload
1586
1587        :param str uuid: The unique identifier for the upload
1588        :param UploadMetadataChangeCommandModel change: The metadata changes to apply
1589        :return: A single-entry map of the upload's uuid to its updated metadata
1590        :rtype: dict[str, UploadMetadataModel]
1591        """
1592        pass
1593
1594    @abstractmethod
1595    def find_upload_preview(self, uuid: str, nature: str) -> dict:
1596        """ Retrieve a preview of an uploaded file's data, interpreted according to the given nature
1597
1598        :param str uuid: The unique identifier for the upload
1599        :param str nature: The nature to interpret the upload as (e.g. 'track', 'route', 'coverage')
1600        :return: A raw dict with 'success' and 'preview' keys - the preview shape is nature-dependent
1601        :rtype: dict
1602        """
1603        pass
1604
1605    @abstractmethod
1606    def process_upload(self, uuid: str) -> dict[str, UploadMetadataModel]:
1607        """ Commit/process an uploaded file into inMotion, based on its assigned nature
1608
1609        :param str uuid: The unique identifier for the upload
1610        :return: A single-entry map of the upload's uuid to its updated metadata
1611        :rtype: dict[str, UploadMetadataModel]
1612        """
1613        pass
1614
1615    @abstractmethod
1616    def cancel_upload(self, uuid: str) -> bool:
1617        """ Cancel an in-progress upload, removing its tracked state
1618
1619        :param str uuid: The unique identifier for the upload
1620        :return: True if the upload was successfully cancelled
1621        :rtype: bool
1622        """
1623        pass
1624
1625    @abstractmethod
1626    def delete_upload(self, uuid: str) -> bool:
1627        """ Delete an upload's tracked state
1628
1629        :param str uuid: The unique identifier for the upload
1630        :return: True if the upload was successfully deleted
1631        :rtype: bool
1632        """
1633        pass
1634
1635    @abstractmethod
1636    def find_uploads(self, account: str) -> dict[str, UploadMetadataModel]:
1637        """ Retrieve all tracked uploads for an account
1638
1639        :param str account: The unique key of the account
1640        :return: A map of upload uuid to its metadata
1641        :rtype: dict[str, UploadMetadataModel]
1642        """
1643        pass
1644
1645    @abstractmethod
1646    def upload_diagnostics(self, account: str, file_path: str, content_type: str = 'application/octet-stream') -> list[str]:
1647        """ Upload a diagnostics file (e.g. a crash log or device dump) for a specific account,
1648        stored server-side without going through the tracked-upload/process pipeline
1649
1650        :param str account: The unique key of the account to upload the file to
1651        :param str file_path: The path to the local file to upload
1652        :param str content_type: The MIME type to declare for the uploaded file
1653        :return: The server-assigned filename(s) the diagnostics file was stored under
1654        :rtype: list[str]
1655        """
1656        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def upload_file( self, account: str, file_path: str, content_type: str = 'application/octet-stream') -> dict[str, inmotion.models.UploadMetadataModel]:
1561    @abstractmethod
1562    def upload_file(self, account: str, file_path: str, content_type: str = 'application/octet-stream') -> dict[str, UploadMetadataModel]:
1563        """ Upload a file to the nominated account using a multipart form
1564
1565        :param str account: The unique key of the account to upload the file to
1566        :param str file_path: The path to the local file to upload
1567        :param str content_type: The MIME type to declare for the uploaded file
1568        :return: A map of the new upload's uuid to its metadata (one entry per uploaded file)
1569        :rtype: dict[str, UploadMetadataModel]
1570        """
1571        pass

Upload a file to the nominated account using a multipart form

Parameters
  • str account: The unique key of the account to upload the file to
  • str file_path: The path to the local file to upload
  • str content_type: The MIME type to declare for the uploaded file
Returns

A map of the new upload's uuid to its metadata (one entry per uploaded file)

@abstractmethod
def find_upload_metadata(self, uuid: str) -> inmotion.models.UploadMetadataModel:
1573    @abstractmethod
1574    def find_upload_metadata(self, uuid: str) -> UploadMetadataModel:
1575        """ Retrieve the metadata for a specific file upload
1576
1577        :param str uuid: The unique identifier for the upload
1578        :return: The upload's metadata
1579        :rtype: UploadMetadataModel
1580        """
1581        pass

Retrieve the metadata for a specific file upload

Parameters
  • str uuid: The unique identifier for the upload
Returns

The upload's metadata

@abstractmethod
def update_upload_metadata( self, uuid: str, change: inmotion.models.UploadMetadataChangeCommandModel) -> dict[str, inmotion.models.UploadMetadataModel]:
1583    @abstractmethod
1584    def update_upload_metadata(self, uuid: str, change: UploadMetadataChangeCommandModel) -> dict[str, UploadMetadataModel]:
1585        """ Update the metadata (mime type, nature, attributes) for a specific file upload
1586
1587        :param str uuid: The unique identifier for the upload
1588        :param UploadMetadataChangeCommandModel change: The metadata changes to apply
1589        :return: A single-entry map of the upload's uuid to its updated metadata
1590        :rtype: dict[str, UploadMetadataModel]
1591        """
1592        pass

Update the metadata (mime type, nature, attributes) for a specific file upload

Parameters
  • str uuid: The unique identifier for the upload
  • UploadMetadataChangeCommandModel change: The metadata changes to apply
Returns

A single-entry map of the upload's uuid to its updated metadata

@abstractmethod
def find_upload_preview(self, uuid: str, nature: str) -> dict:
1594    @abstractmethod
1595    def find_upload_preview(self, uuid: str, nature: str) -> dict:
1596        """ Retrieve a preview of an uploaded file's data, interpreted according to the given nature
1597
1598        :param str uuid: The unique identifier for the upload
1599        :param str nature: The nature to interpret the upload as (e.g. 'track', 'route', 'coverage')
1600        :return: A raw dict with 'success' and 'preview' keys - the preview shape is nature-dependent
1601        :rtype: dict
1602        """
1603        pass

Retrieve a preview of an uploaded file's data, interpreted according to the given nature

Parameters
  • str uuid: The unique identifier for the upload
  • str nature: The nature to interpret the upload as (e.g. 'track', 'route', 'coverage')
Returns

A raw dict with 'success' and 'preview' keys - the preview shape is nature-dependent

@abstractmethod
def process_upload(self, uuid: str) -> dict[str, inmotion.models.UploadMetadataModel]:
1605    @abstractmethod
1606    def process_upload(self, uuid: str) -> dict[str, UploadMetadataModel]:
1607        """ Commit/process an uploaded file into inMotion, based on its assigned nature
1608
1609        :param str uuid: The unique identifier for the upload
1610        :return: A single-entry map of the upload's uuid to its updated metadata
1611        :rtype: dict[str, UploadMetadataModel]
1612        """
1613        pass

Commit/process an uploaded file into inMotion, based on its assigned nature

Parameters
  • str uuid: The unique identifier for the upload
Returns

A single-entry map of the upload's uuid to its updated metadata

@abstractmethod
def cancel_upload(self, uuid: str) -> bool:
1615    @abstractmethod
1616    def cancel_upload(self, uuid: str) -> bool:
1617        """ Cancel an in-progress upload, removing its tracked state
1618
1619        :param str uuid: The unique identifier for the upload
1620        :return: True if the upload was successfully cancelled
1621        :rtype: bool
1622        """
1623        pass

Cancel an in-progress upload, removing its tracked state

Parameters
  • str uuid: The unique identifier for the upload
Returns

True if the upload was successfully cancelled

@abstractmethod
def delete_upload(self, uuid: str) -> bool:
1625    @abstractmethod
1626    def delete_upload(self, uuid: str) -> bool:
1627        """ Delete an upload's tracked state
1628
1629        :param str uuid: The unique identifier for the upload
1630        :return: True if the upload was successfully deleted
1631        :rtype: bool
1632        """
1633        pass

Delete an upload's tracked state

Parameters
  • str uuid: The unique identifier for the upload
Returns

True if the upload was successfully deleted

@abstractmethod
def find_uploads(self, account: str) -> dict[str, inmotion.models.UploadMetadataModel]:
1635    @abstractmethod
1636    def find_uploads(self, account: str) -> dict[str, UploadMetadataModel]:
1637        """ Retrieve all tracked uploads for an account
1638
1639        :param str account: The unique key of the account
1640        :return: A map of upload uuid to its metadata
1641        :rtype: dict[str, UploadMetadataModel]
1642        """
1643        pass

Retrieve all tracked uploads for an account

Parameters
  • str account: The unique key of the account
Returns

A map of upload uuid to its metadata

@abstractmethod
def upload_diagnostics( self, account: str, file_path: str, content_type: str = 'application/octet-stream') -> list[str]:
1645    @abstractmethod
1646    def upload_diagnostics(self, account: str, file_path: str, content_type: str = 'application/octet-stream') -> list[str]:
1647        """ Upload a diagnostics file (e.g. a crash log or device dump) for a specific account,
1648        stored server-side without going through the tracked-upload/process pipeline
1649
1650        :param str account: The unique key of the account to upload the file to
1651        :param str file_path: The path to the local file to upload
1652        :param str content_type: The MIME type to declare for the uploaded file
1653        :return: The server-assigned filename(s) the diagnostics file was stored under
1654        :rtype: list[str]
1655        """
1656        pass

Upload a diagnostics file (e.g. a crash log or device dump) for a specific account, stored server-side without going through the tracked-upload/process pipeline

Parameters
  • str account: The unique key of the account to upload the file to
  • str file_path: The path to the local file to upload
  • str content_type: The MIME type to declare for the uploaded file
Returns

The server-assigned filename(s) the diagnostics file was stored under

class InMotionUser(abc.ABC):
1382class InMotionUser(ABC):
1383    @abstractmethod
1384    def create_user_against_account(self, account_key: str, privilege_label: str, registration: UserRegistrationModel) -> AccountUserSummaryModel:
1385        """ Register a new user and grant them a privilege level against an account
1386
1387        :param str account_key: The unique key of the account to register the user against
1388        :param str privilege_label: The privilege level to grant ('view', 'contribute', or 'admin';
1389            any other value is treated as 'view' by the server)
1390        :param UserRegistrationModel registration: The definition of the user to create
1391        :return: A summary of the newly created and registered user
1392        :rtype: AccountUserSummaryModel
1393        """
1394        pass
1395
1396    @abstractmethod
1397    def request_password_reset(self, request: UserPasswordRequestModel) -> MessageResponseModel:
1398        """ Request a password reset email be sent to a user
1399
1400        :param UserPasswordRequestModel request: The username or email address of the user
1401        :return: A confirmation message
1402        :rtype: MessageResponseModel
1403        """
1404        pass
1405
1406    @abstractmethod
1407    def find_user_attributes(self) -> UserAttributesModel:
1408        """ Retrieve the attributes of the currently authenticated user
1409
1410        :return: The authenticated user's attributes
1411        :rtype: UserAttributesModel
1412        """
1413        pass
1414
1415    @abstractmethod
1416    def update_user_attributes(self, attributes: UserAttributesModel) -> dict:
1417        """ Update the attributes of the currently authenticated user
1418
1419        :param UserAttributesModel attributes: The updated attributes
1420        :return: A raw confirmation message from the server (not a re-fetch of the attributes)
1421        :rtype: dict
1422        """
1423        pass
1424
1425    @abstractmethod
1426    def unregister_from_account(self, account_key: str) -> UserUnregisteredResponseModel:
1427        """ Unregister the currently authenticated user from an account
1428
1429        :param str account_key: The unique key of the account to unregister from
1430        :return: The result of the unregister operation
1431        :rtype: UserUnregisteredResponseModel
1432        """
1433        pass
1434
1435    @abstractmethod
1436    def create_otc(self) -> OTCModel:
1437        """ Create a one-time code (OTC) key pair for the authenticated user, used to support
1438        device pairing/bootstrap flows. Requires a developer key, which is used to encrypt the
1439        returned private key.
1440
1441        :return: The new one-time code's public/private key pair
1442        :rtype: OTCModel
1443        """
1444        pass
1445
1446    @abstractmethod
1447    def find_mfa_status(self) -> MfaStatusModel:
1448        """ Retrieve MFA enrollment status (enabled, method, enrolled-at) for the authenticated user
1449
1450        :return: The authenticated user's MFA status
1451        :rtype: MfaStatusModel
1452        """
1453        pass
1454
1455    @abstractmethod
1456    def enroll_mfa(self, request: MfaEnrollRequestModel) -> MfaStatusModel:
1457        """ Begin EMAIL MFA enrollment for the authenticated user's own account: requires
1458        re-entering the current password, then emails a live code. MFA does not activate yet -
1459        follow with confirm_mfa_email. TOTP/SMS are rejected here - use begin_totp_enrollment
1460        instead.
1461
1462        :param MfaEnrollRequestModel request: The method to enroll in and the current password
1463        :return: The user's MFA status (still not enabled)
1464        :rtype: MfaStatusModel
1465        """
1466        pass
1467
1468    @abstractmethod
1469    def confirm_mfa_email(self, request: TotpConfirmRequestModel) -> MfaStatusModel:
1470        """ Confirm a pending EMAIL enrollment (from enroll_mfa) with the live code just emailed
1471        to the account. Activates MFA (method EMAIL) only on success.
1472
1473        :param TotpConfirmRequestModel request: The code that was emailed
1474        :return: The user's MFA status, now enabled if the code was valid
1475        :rtype: MfaStatusModel
1476        """
1477        pass
1478
1479    @abstractmethod
1480    def begin_totp_enrollment(self, request: TotpEnrollBeginRequestModel) -> TotpEnrollmentBeginResultModel:
1481        """ Generate a new TOTP secret and backup/recovery codes for the authenticated user's own
1482        account. Does not activate MFA yet - follow with confirm_totp_enrollment. Requires
1483        re-entering the current password. `backupCodes` are returned in plaintext exactly once.
1484
1485        :param TotpEnrollBeginRequestModel request: The current password
1486        :return: The new TOTP secret/QR URI/backup codes
1487        :rtype: TotpEnrollmentBeginResultModel
1488        """
1489        pass
1490
1491    @abstractmethod
1492    def confirm_totp_enrollment(self, request: TotpConfirmRequestModel) -> MfaStatusModel:
1493        """ Confirm a pending TOTP enrollment (from begin_totp_enrollment) with a live code from
1494        the authenticator app just configured. Activates MFA (method TOTP) only on success.
1495
1496        :param TotpConfirmRequestModel request: The code from the authenticator app
1497        :return: The user's MFA status, now enabled if the code was valid
1498        :rtype: MfaStatusModel
1499        """
1500        pass
1501
1502    @abstractmethod
1503    def regenerate_totp_backup_codes(self, request: TotpBackupCodesRegenerateRequestModel) -> MfaBackupCodesModel:
1504        """ Regenerate the authenticated user's TOTP backup/recovery codes, invalidating the
1505        previous set entirely. Requires re-entering the current password, and that TOTP is
1506        currently the account's enabled MFA method.
1507
1508        :param TotpBackupCodesRegenerateRequestModel request: The current password
1509        :return: The new set of backup/recovery codes, plaintext, shown exactly once
1510        :rtype: MfaBackupCodesModel
1511        """
1512        pass
1513
1514    @abstractmethod
1515    def disable_mfa(self, request: MfaDisableRequestModel) -> MfaStatusModel:
1516        """ Disable one MFA method for the caller's own account (not all of them at once). Requires
1517        re-entering the current password. If it was the last enrolled method, MFA is turned off overall.
1518
1519        :param MfaDisableRequestModel request: The method to disable and the current password
1520        :return: The user's MFA status after the method was disabled
1521        :rtype: MfaStatusModel
1522        """
1523        pass
1524
1525    @abstractmethod
1526    def set_preferred_mfa_method(self, request: MfaPreferredMethodRequestModel) -> MfaStatusModel:
1527        """ Choose which already-enrolled MFA method is challenged at login, overriding the
1528        TOTP-then-EMAIL default. Rejected (400) if the method isn't currently enrolled.
1529
1530        :param MfaPreferredMethodRequestModel request: The method to prefer
1531        :return: The user's MFA status, with the new `preferredMethod`
1532        :rtype: MfaStatusModel
1533        """
1534        pass
1535
1536    @abstractmethod
1537    def find_friend_invite(self, token: str) -> FriendInviteInfoModel:
1538        """ Look up a friend-invite's sign-up prefill details. Public - the invitee has no inMotion
1539        identity yet. Fails (404) if the token is invalid, expired, revoked or already accepted.
1540
1541        :param str token: The invite's token
1542        :return: The account and inviter the invite is from, and the email it was issued to
1543        :rtype: FriendInviteInfoModel
1544        """
1545        pass
1546
1547    @abstractmethod
1548    def accept_friend_invite(self, token: str, registration: UserRegistrationModel) -> AccountUserSummaryModel:
1549        """ Accept a friend-invite: creates the invitee's user and attaches it to the inviting account at
1550        a fixed low-privilege tier. Public. The registration's email is ignored - the invite's own is used.
1551
1552        :param str token: The invite's token
1553        :param UserRegistrationModel registration: The new user's registration details
1554        :return: The created user, as a member of the inviting account
1555        :rtype: AccountUserSummaryModel
1556        """
1557        pass

Helper class that provides a standard way to create an ABC using inheritance.

@abstractmethod
def create_user_against_account( self, account_key: str, privilege_label: str, registration: inmotion.models.UserRegistrationModel) -> inmotion.models.AccountUserSummaryModel:
1383    @abstractmethod
1384    def create_user_against_account(self, account_key: str, privilege_label: str, registration: UserRegistrationModel) -> AccountUserSummaryModel:
1385        """ Register a new user and grant them a privilege level against an account
1386
1387        :param str account_key: The unique key of the account to register the user against
1388        :param str privilege_label: The privilege level to grant ('view', 'contribute', or 'admin';
1389            any other value is treated as 'view' by the server)
1390        :param UserRegistrationModel registration: The definition of the user to create
1391        :return: A summary of the newly created and registered user
1392        :rtype: AccountUserSummaryModel
1393        """
1394        pass

Register a new user and grant them a privilege level against an account

Parameters
  • str account_key: The unique key of the account to register the user against
  • str privilege_label: The privilege level to grant ('view', 'contribute', or 'admin'; any other value is treated as 'view' by the server)
  • UserRegistrationModel registration: The definition of the user to create
Returns

A summary of the newly created and registered user

@abstractmethod
def request_password_reset( self, request: inmotion.models.UserPasswordRequestModel) -> inmotion.models.MessageResponseModel:
1396    @abstractmethod
1397    def request_password_reset(self, request: UserPasswordRequestModel) -> MessageResponseModel:
1398        """ Request a password reset email be sent to a user
1399
1400        :param UserPasswordRequestModel request: The username or email address of the user
1401        :return: A confirmation message
1402        :rtype: MessageResponseModel
1403        """
1404        pass

Request a password reset email be sent to a user

Parameters
  • UserPasswordRequestModel request: The username or email address of the user
Returns

A confirmation message

@abstractmethod
def find_user_attributes(self) -> inmotion.models.UserAttributesModel:
1406    @abstractmethod
1407    def find_user_attributes(self) -> UserAttributesModel:
1408        """ Retrieve the attributes of the currently authenticated user
1409
1410        :return: The authenticated user's attributes
1411        :rtype: UserAttributesModel
1412        """
1413        pass

Retrieve the attributes of the currently authenticated user

Returns

The authenticated user's attributes

@abstractmethod
def update_user_attributes(self, attributes: inmotion.models.UserAttributesModel) -> dict:
1415    @abstractmethod
1416    def update_user_attributes(self, attributes: UserAttributesModel) -> dict:
1417        """ Update the attributes of the currently authenticated user
1418
1419        :param UserAttributesModel attributes: The updated attributes
1420        :return: A raw confirmation message from the server (not a re-fetch of the attributes)
1421        :rtype: dict
1422        """
1423        pass

Update the attributes of the currently authenticated user

Parameters
  • UserAttributesModel attributes: The updated attributes
Returns

A raw confirmation message from the server (not a re-fetch of the attributes)

@abstractmethod
def unregister_from_account(self, account_key: str) -> inmotion.models.UserUnregisteredResponseModel:
1425    @abstractmethod
1426    def unregister_from_account(self, account_key: str) -> UserUnregisteredResponseModel:
1427        """ Unregister the currently authenticated user from an account
1428
1429        :param str account_key: The unique key of the account to unregister from
1430        :return: The result of the unregister operation
1431        :rtype: UserUnregisteredResponseModel
1432        """
1433        pass

Unregister the currently authenticated user from an account

Parameters
  • str account_key: The unique key of the account to unregister from
Returns

The result of the unregister operation

@abstractmethod
def create_otc(self) -> inmotion.models.OTCModel:
1435    @abstractmethod
1436    def create_otc(self) -> OTCModel:
1437        """ Create a one-time code (OTC) key pair for the authenticated user, used to support
1438        device pairing/bootstrap flows. Requires a developer key, which is used to encrypt the
1439        returned private key.
1440
1441        :return: The new one-time code's public/private key pair
1442        :rtype: OTCModel
1443        """
1444        pass

Create a one-time code (OTC) key pair for the authenticated user, used to support device pairing/bootstrap flows. Requires a developer key, which is used to encrypt the returned private key.

Returns

The new one-time code's public/private key pair

@abstractmethod
def find_mfa_status(self) -> inmotion.models.MfaStatusModel:
1446    @abstractmethod
1447    def find_mfa_status(self) -> MfaStatusModel:
1448        """ Retrieve MFA enrollment status (enabled, method, enrolled-at) for the authenticated user
1449
1450        :return: The authenticated user's MFA status
1451        :rtype: MfaStatusModel
1452        """
1453        pass

Retrieve MFA enrollment status (enabled, method, enrolled-at) for the authenticated user

Returns

The authenticated user's MFA status

@abstractmethod
def enroll_mfa( self, request: inmotion.models.MfaEnrollRequestModel) -> inmotion.models.MfaStatusModel:
1455    @abstractmethod
1456    def enroll_mfa(self, request: MfaEnrollRequestModel) -> MfaStatusModel:
1457        """ Begin EMAIL MFA enrollment for the authenticated user's own account: requires
1458        re-entering the current password, then emails a live code. MFA does not activate yet -
1459        follow with confirm_mfa_email. TOTP/SMS are rejected here - use begin_totp_enrollment
1460        instead.
1461
1462        :param MfaEnrollRequestModel request: The method to enroll in and the current password
1463        :return: The user's MFA status (still not enabled)
1464        :rtype: MfaStatusModel
1465        """
1466        pass

Begin EMAIL MFA enrollment for the authenticated user's own account: requires re-entering the current password, then emails a live code. MFA does not activate yet - follow with confirm_mfa_email. TOTP/SMS are rejected here - use begin_totp_enrollment instead.

Parameters
  • MfaEnrollRequestModel request: The method to enroll in and the current password
Returns

The user's MFA status (still not enabled)

@abstractmethod
def confirm_mfa_email( self, request: inmotion.models.TotpConfirmRequestModel) -> inmotion.models.MfaStatusModel:
1468    @abstractmethod
1469    def confirm_mfa_email(self, request: TotpConfirmRequestModel) -> MfaStatusModel:
1470        """ Confirm a pending EMAIL enrollment (from enroll_mfa) with the live code just emailed
1471        to the account. Activates MFA (method EMAIL) only on success.
1472
1473        :param TotpConfirmRequestModel request: The code that was emailed
1474        :return: The user's MFA status, now enabled if the code was valid
1475        :rtype: MfaStatusModel
1476        """
1477        pass

Confirm a pending EMAIL enrollment (from enroll_mfa) with the live code just emailed to the account. Activates MFA (method EMAIL) only on success.

Parameters
  • TotpConfirmRequestModel request: The code that was emailed
Returns

The user's MFA status, now enabled if the code was valid

@abstractmethod
def begin_totp_enrollment( self, request: inmotion.models.TotpEnrollBeginRequestModel) -> inmotion.models.TotpEnrollmentBeginResultModel:
1479    @abstractmethod
1480    def begin_totp_enrollment(self, request: TotpEnrollBeginRequestModel) -> TotpEnrollmentBeginResultModel:
1481        """ Generate a new TOTP secret and backup/recovery codes for the authenticated user's own
1482        account. Does not activate MFA yet - follow with confirm_totp_enrollment. Requires
1483        re-entering the current password. `backupCodes` are returned in plaintext exactly once.
1484
1485        :param TotpEnrollBeginRequestModel request: The current password
1486        :return: The new TOTP secret/QR URI/backup codes
1487        :rtype: TotpEnrollmentBeginResultModel
1488        """
1489        pass

Generate a new TOTP secret and backup/recovery codes for the authenticated user's own account. Does not activate MFA yet - follow with confirm_totp_enrollment. Requires re-entering the current password. backupCodes are returned in plaintext exactly once.

Parameters
  • TotpEnrollBeginRequestModel request: The current password
Returns

The new TOTP secret/QR URI/backup codes

@abstractmethod
def confirm_totp_enrollment( self, request: inmotion.models.TotpConfirmRequestModel) -> inmotion.models.MfaStatusModel:
1491    @abstractmethod
1492    def confirm_totp_enrollment(self, request: TotpConfirmRequestModel) -> MfaStatusModel:
1493        """ Confirm a pending TOTP enrollment (from begin_totp_enrollment) with a live code from
1494        the authenticator app just configured. Activates MFA (method TOTP) only on success.
1495
1496        :param TotpConfirmRequestModel request: The code from the authenticator app
1497        :return: The user's MFA status, now enabled if the code was valid
1498        :rtype: MfaStatusModel
1499        """
1500        pass

Confirm a pending TOTP enrollment (from begin_totp_enrollment) with a live code from the authenticator app just configured. Activates MFA (method TOTP) only on success.

Parameters
  • TotpConfirmRequestModel request: The code from the authenticator app
Returns

The user's MFA status, now enabled if the code was valid

@abstractmethod
def regenerate_totp_backup_codes( self, request: inmotion.models.TotpBackupCodesRegenerateRequestModel) -> inmotion.models.MfaBackupCodesModel:
1502    @abstractmethod
1503    def regenerate_totp_backup_codes(self, request: TotpBackupCodesRegenerateRequestModel) -> MfaBackupCodesModel:
1504        """ Regenerate the authenticated user's TOTP backup/recovery codes, invalidating the
1505        previous set entirely. Requires re-entering the current password, and that TOTP is
1506        currently the account's enabled MFA method.
1507
1508        :param TotpBackupCodesRegenerateRequestModel request: The current password
1509        :return: The new set of backup/recovery codes, plaintext, shown exactly once
1510        :rtype: MfaBackupCodesModel
1511        """
1512        pass

Regenerate the authenticated user's TOTP backup/recovery codes, invalidating the previous set entirely. Requires re-entering the current password, and that TOTP is currently the account's enabled MFA method.

Parameters
  • TotpBackupCodesRegenerateRequestModel request: The current password
Returns

The new set of backup/recovery codes, plaintext, shown exactly once

@abstractmethod
def disable_mfa( self, request: inmotion.models.MfaDisableRequestModel) -> inmotion.models.MfaStatusModel:
1514    @abstractmethod
1515    def disable_mfa(self, request: MfaDisableRequestModel) -> MfaStatusModel:
1516        """ Disable one MFA method for the caller's own account (not all of them at once). Requires
1517        re-entering the current password. If it was the last enrolled method, MFA is turned off overall.
1518
1519        :param MfaDisableRequestModel request: The method to disable and the current password
1520        :return: The user's MFA status after the method was disabled
1521        :rtype: MfaStatusModel
1522        """
1523        pass

Disable one MFA method for the caller's own account (not all of them at once). Requires re-entering the current password. If it was the last enrolled method, MFA is turned off overall.

Parameters
  • MfaDisableRequestModel request: The method to disable and the current password
Returns

The user's MFA status after the method was disabled

@abstractmethod
def set_preferred_mfa_method( self, request: inmotion.models.MfaPreferredMethodRequestModel) -> inmotion.models.MfaStatusModel:
1525    @abstractmethod
1526    def set_preferred_mfa_method(self, request: MfaPreferredMethodRequestModel) -> MfaStatusModel:
1527        """ Choose which already-enrolled MFA method is challenged at login, overriding the
1528        TOTP-then-EMAIL default. Rejected (400) if the method isn't currently enrolled.
1529
1530        :param MfaPreferredMethodRequestModel request: The method to prefer
1531        :return: The user's MFA status, with the new `preferredMethod`
1532        :rtype: MfaStatusModel
1533        """
1534        pass

Choose which already-enrolled MFA method is challenged at login, overriding the TOTP-then-EMAIL default. Rejected (400) if the method isn't currently enrolled.

Parameters
  • MfaPreferredMethodRequestModel request: The method to prefer
Returns

The user's MFA status, with the new preferredMethod

@abstractmethod
def find_friend_invite(self, token: str) -> inmotion.models.FriendInviteInfoModel:
1536    @abstractmethod
1537    def find_friend_invite(self, token: str) -> FriendInviteInfoModel:
1538        """ Look up a friend-invite's sign-up prefill details. Public - the invitee has no inMotion
1539        identity yet. Fails (404) if the token is invalid, expired, revoked or already accepted.
1540
1541        :param str token: The invite's token
1542        :return: The account and inviter the invite is from, and the email it was issued to
1543        :rtype: FriendInviteInfoModel
1544        """
1545        pass

Look up a friend-invite's sign-up prefill details. Public - the invitee has no inMotion identity yet. Fails (404) if the token is invalid, expired, revoked or already accepted.

Parameters
  • str token: The invite's token
Returns

The account and inviter the invite is from, and the email it was issued to

@abstractmethod
def accept_friend_invite( self, token: str, registration: inmotion.models.UserRegistrationModel) -> inmotion.models.AccountUserSummaryModel:
1547    @abstractmethod
1548    def accept_friend_invite(self, token: str, registration: UserRegistrationModel) -> AccountUserSummaryModel:
1549        """ Accept a friend-invite: creates the invitee's user and attaches it to the inviting account at
1550        a fixed low-privilege tier. Public. The registration's email is ignored - the invite's own is used.
1551
1552        :param str token: The invite's token
1553        :param UserRegistrationModel registration: The new user's registration details
1554        :return: The created user, as a member of the inviting account
1555        :rtype: AccountUserSummaryModel
1556        """
1557        pass

Accept a friend-invite: creates the invitee's user and attaches it to the inviting account at a fixed low-privilege tier. Public. The registration's email is ignored - the invite's own is used.

Parameters
  • str token: The invite's token
  • UserRegistrationModel registration: The new user's registration details
Returns

The created user, as a member of the inviting account