Functions

Functions are bite-sized pieces of Python code that you package as a zip, upload via the Samsara dashboard, and invoke through various triggers — manually, via the API, on a schedule, or from alert workflows. Samsara handles the heavy lifting of running your code in a managed serverless runtime, so you can automate workflows, process data, and integrate with external systems without hosting your own infrastructure.

Common use cases include:

  • Proof-of-concept automations and customer-specific workflows
  • Alert-driven pipelines (media retrieval, scheduled analysis, notifications)
  • Nightly syncs and reports
  • Lightweight transformations to third-party services

Functions are available in all Samsara cloud regions. Use the regional API base URL that matches your dashboard (cloud.samsara.com, cloud.eu.samsara.com, or cloud.ca.samsara.com) when calling the Samsara REST API.

Quick start

The golden path is: Write → Bundle → Run → Observe. Write a simple Python handler, zip it, upload it, trigger a run, and read the logs. Iterate in small steps.

Ready-to-use templates in the functions-examples repository can get you up to speed quicker:

If you just want to try Functions without setting up developer tooling, use the GitHub Importer with default settings, accessible from the Function editor in the dashboard.

1. Write

Create a small Python file and define your entrypoint:

def main(event, _):
    ...
  • Read inputs from event — a flat dictionary of strings. Parse to the types you need and validate.
  • Don't rely on return values — production ignores them. Prefer clear, structured logs and side effects (HTTP calls, storage writes).
  • Retrieve secrets at runtime (see Secrets below).

2. Bundle

Save your files into a folder (for example, a src/ directory) and create a zip (≤ 50 MB compressed). On macOS, right-click the folder in Finder and choose Compress; on Windows use Send to → Compressed (zipped) folder. Prefer a CLI? samsara-fn bundle ./src ./dist creates a ready-to-upload zip (see Local development).

If you need extra Python dependencies, vendor them into the zip (see Provided dependencies).

3. Configure and upload

In the Samsara dashboard, go to Settings → Developer → Functions and create or edit a Function:

  • Set Name, Description, and Visibility. Names are unique, up to 35 characters, and cannot be changed later.
  • Add Event parameters — these become keys in event.
  • Add Secrets — values are stored only in the dashboard.
  • Upload your zip and set the Handler as module.function (for example, entrypoint.main when your file is entrypoint.py with def main).
  • Optionally enable a Schedule.

Permissions: Users with Standard Admin or Full Admin roles have read/write access to Functions. Read-only Admin users have read access. Other users can be granted access through a custom role permission.

4. Run and observe

  1. Manual: In the editor tab, set an Event parameter override and trigger a run.
  2. API: Invoke with your regional host and a token with the Functions > Write scope:
curl --location 'https://api.samsara.com/functions/<your-function-name>/runs' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer samsara_api_xxx' \
  --data '{"paramsOverride": {}}'
{ "data": { "correlationId": "084890b1-9c8a-4ba8-bee4-ec7c47b97199" } }
  1. Alerts: In Alerts (Workflows) → Actions → Execute Function, choose your Function.
  2. Schedule: Enable and configure in the editor.
  3. Observe: Editor → Logs. Log the correlation ID (event["SamsaraFunctionCorrelationId"]) to tie runs to logs.

Handler contract and event shape

Every invocation receives an event object (a flat Python dictionary of strings) as the first argument to your handler. The event always includes:

  • SamsaraFunctionTriggerSource — how the run was triggered (manual, api, schedule, or alert)
  • SamsaraFunctionCorrelationId — a unique ID for the run; log it to find the run in logs instantly

Trigger-specific fields:

TriggerEvent contents
Manual / APIYour configured parameters + any overrides you provide
ScheduleYour configured parameters + SamsaraFunctionTriggerSource="schedule"
AlertYour configured parameters + assetId or driverId (one of them blank, depending on the alert trigger), alertIncidentTime, alertConfigurationId

Example event for an alert-triggered run:

{
  "SamsaraFunctionTriggerSource": "alert",
  "SamsaraFunctionCorrelationId": "0a793932-3d3e-4c5c-bff7-c27bed462b9e",
  "assetId": "123214",
  "driverId": "",
  "alertConfigurationId": "407a985a-6784-4a16-8489-2e0480100c46",
  "alertIncidentTime": "1758119598619"
}

Branch on the trigger source when one Function serves multiple triggers:

def main(event, _):
    trigger_source = event["SamsaraFunctionTriggerSource"]
    if trigger_source == "alert":
        vehicle_id = event["assetId"]
        # alert-specific work
    if trigger_source == "schedule":
        # scheduled work
        ...

Parameters and secrets

Parameters

Treat the event like a small envelope of strings — describe what you need in the editor, then override values when testing.

  • Define parameters in the editor under Event parameters. Parameter names must be unique.
  • Override per run in the editor (Event parameter override) or via the API paramsOverride. Overrides apply to that run only and do not persist.

Secrets

Secrets are for credentials and keys you don't want in code — API tokens, passwords, provider keys. Configure them once in the editor; retrieve them at runtime as a dictionary.

  • Configure in Editor → Secrets. Values live only in the dashboard; after saving, only key names can be viewed outside the Function runtime.
  • Secrets are encrypted and scoped to your organization and Function.

Minimal example, part of basic/just-secrets:

from samsarafnsecrets import get_secrets

def main(_, __):
    secrets = get_secrets()
    print({"secretsCount": len(secrets)})

Using a secret with a third-party client, part of advanced/ppe-detection:

from samsarafnsecrets import get_secrets

client = openai.OpenAI(api_key=get_secrets()["OPENAI_KEY"])

Practical notes:

  • Store provider keys with clear names (for example, SAMSARA_KEY, OPENAI_KEY) and reference exact keys.
  • Never log plaintext secret values; only send them over HTTPS.
  • Never store secrets in Storage. If you encrypt artifacts before saving them to Storage, keep the encryption keys in Secrets.

Storage

Most pipelines need a place to put artifacts or a small amount of state. Functions provide three storage options:

StorageUse for
File storage (S3-backed)Blobs and artifacts: images, CSVs, reports
Key-value databaseLightweight state: checkpoints, pipeline stages
Temporary runtime storage (/tmp)Scratch files during a single invocation — not persisted across runs

File storage

Use the storage helper to put/get/list/delete binary content, part of basic/persistent-storage:

from samsarafnstorage import get_storage

storage = get_storage()
storage.put(Key="test.csv", Body=b"col1,col2\nvalue1,value2")
blob = storage.get_body(Key="test.csv")
for key in storage.list_keys(Prefix=""):
    print(key)
storage.delete(Key="test.csv")

You can also manage files from the Storage tab in the dashboard.

Key-value database

A namespaced wrapper over storage for lightweight state, also part of basic/persistent-storage:

from samsarafnstorage import get_database

db = get_database("my-feature")
db.put("unique-id", "123")
db.put_dict("other-unique-id", {"name": "object", "tags": ["descriptive"]})
print(db.get("unique-id"))
print(db.get_dict("other-unique-id"))
print(db.keys())
db.delete("unique-id")

Temporary runtime storage

Scratch space during a single invocation, part of basic/temporary-runtime-storage:

from samsarafntempstorage import temp_storage_path

tmp = temp_storage_path()
f = tmp / "my.csv"
f.write_text("name,age\nJohn,25\nJane,30\n")

Storage guidance

  • Prefer small, incremental writes; avoid tight loops waiting on large downloads.
  • Key prefixes follow S3 semantics — use / in keys to mimic folders.
  • Namespace keys clearly; use the database wrapper for pipeline stages.
  • Never store secrets in Storage. For sensitive artifacts, encrypt on write and keep keys in Secrets.

Direct AWS access

If you prefer the REST API or boto3 directly instead of the helpers:

  • The storage bucket accessible at runtime is set in the environment variable SamsaraFunctionStorageName.
  • The runtime is allowed to execute s3:GetObject, s3:ListBucket, s3:PutObject, and s3:DeleteObject.
  • Privileged access to secrets and storage is facilitated through role chaining: call STS assume_role with the role in SamsaraFunctionExecRoleArn, then pass the returned credentials to your AWS client. See basic/persistent-storage for a complete example:
def get_credentials(force_refresh=False) -> dict[str, str]:
    global _credentials
    if _credentials is not None and not force_refresh:
        return _credentials

    sts = boto3.client("sts")
    res = sts.assume_role(
        RoleArn=os.environ["SamsaraFunctionExecRoleArn"],
        RoleSessionName=os.environ["SamsaraFunctionName"],
    )
    _credentials = {
        "aws_access_key_id": res["Credentials"]["AccessKeyId"],
        "aws_secret_access_key": res["Credentials"]["SecretAccessKey"],
        "aws_session_token": res["Credentials"]["SessionToken"],
    }
    return _credentials

Triggers

Functions run in four ways. The event always includes SamsaraFunctionTriggerSource so you can tell which path you're in. Start with manual or API runs for validation, then wire up schedules or alerts when the behavior is ready.

TriggerDescription
ManualRun from the Function editor with per-run parameter overrides. Best for testing.
APIProgrammatic invocation — best for external systems and scripts. Requires a token with the Functions > Write scope.
ScheduleSimple cadences (for example, daily or weekly) at specific times of day, configured in the editor.
AlertConfigure the Execute Function action in Alerts (Workflows). The Function must be visible to customer users to appear as an alert action.

API example (EU region):

curl --location 'https://api.eu.samsara.com/functions/status-triggerer/runs' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer samsara_api_xxx' \
  --data '{"paramsOverride": {}}'

The response includes a correlationId — the same value your handler receives as event["SamsaraFunctionCorrelationId"].

Runtime environment and limits

PropertyValue
RuntimePython 3.12, x86_64
PackagingZip only, ≤ 50 MB compressed
Memory1,769 MB (~1 vCPU)
Timeout15 minutes
Temporary storage (/tmp)512 MB
Invocation modelAsynchronous; no automatic retries
Log retention90 days

Framework-provided environment variables available at runtime:

  • SamsaraFunctionExecRoleArn
  • SamsaraFunctionSecretsPath
  • SamsaraFunctionStorageName
  • SamsaraFunctionName
  • SamsaraFunctionOrgId
  • SamsaraFunctionCodePath
  • SamsaraFunctionTempStoragePath

Behavioral constraints:

  • Custom environment variables are not supported — pass data via event parameters or Storage.
  • Custom Lambda layers are not supported — one platform-managed layer provides curated dependencies; vendor anything else into your zip.
  • Handler naming follows AWS Lambda conventions (module.function).
  • When a Function is visible to customer users, it runs with reserved concurrency of 1 per organization — plan for queuing in high-throughput alert scenarios.

Provided dependencies

The runtime provides a curated set of dependencies out of the box. Notable ones:

PackageUse for
samsara-apiOfficial SDK for the Samsara REST API
requestsHTTP client for REST calls; pairs well with secrets for auth headers
aiohttpAsync HTTP client/server for concurrent I/O
pillow (PIL)Image processing (resize, encode/decode)
lxmlRobust XML/HTML parsing
paramikoSSH/SFTP for secure file transfers
cryptographySign/verify or encrypt/decrypt payloads
geopyGeocoding and geodesy helpers
pytzTimezone conversions for scheduled workflows
zeepSOAP client for legacy enterprise integrations
tenacityExplicit, bounded retry logic for outbound calls
requests-toolbeltMultipart uploads and advanced requests use cases

Run samsara-fn dependencies latest for the authoritative, full set with pinned versions.

For anything not in the curated set, vendor the dependency into your zip and add it to sys.path, as shown in basic/additional-python-dependencies:

from samsarafndeps import setup_additional_dependency_path

setup_additional_dependency_path("lib")

import cowsay

When calling the Samsara API, prefer the Samsara Python SDK (samsara-api, provided in the runtime) over hand-written HTTP requests.

Observability

Executions tab

The Executions tab in the dashboard visualizes run events — starts, successes, errors, and timeouts. You can inspect the duration of a run, the parameters used to invoke it, and the handler's return value.

A Function reports an error only if the runtime throws an exception. The return value is irrelevant in this context.

Alert notifications on Function runs

For push notifications on Function runs, configure an alert. A single configuration can trigger a notification (for example, an email) for a set of Functions and events: starts, successes, errors, and timeouts.

Logs

  • Logs are retained for 90 days and can be requested in batches.
  • Navigate to Editor → Logs. Use Refresh to Latest Hour, fuzzy search for terms or the correlation ID, or Download as JSON to filter locally.
  • Include the correlation ID in your messages to trace runs. The Lambda-defined RequestId is different from SamsaraFunctionCorrelationId — prefer the latter.
  • Avoid logging secrets or sensitive payloads.

Minimal logging pattern:

def main(event, _):
    corr_id = event["SamsaraFunctionCorrelationId"]
    print(corr_id, "Function started")
    # ... work ...
    result = {}
    print(corr_id, "Function finished", result)

For structured JSON logs with log levels, see basic/correlation-logging:

from samsarafnlogs import setup_logger_once, log

def main(params, _):
    setup_logger_once(params)

    log("Whoops!", level="error")

Local development with samsara-fn

The optional samsara-fn CLI simulator gives you a tight local loop: bundle quickly, run a trigger locally, and inspect output without touching production. It mirrors the production event shape and stubs key AWS calls (sts.assume_role, ssm.get_parameter, and the S3 object operations). Third-party HTTP calls still execute normally unless you stub them.

Install into a virtual environment:

python3 -m venv venv
source venv/bin/activate          # Mac/Linux
# .\venv\Scripts\Activate.ps1     # Windows PowerShell

pip install samsara-fn

Common commands:

CommandPurpose
samsara-fn --helpOverview of capabilities and subcommands
samsara-fn templates just-secrets <dir>Copy a minimal secrets example
samsara-fn bundle ./src ./distPackage a zip; review warnings; use --ignore-file if needed
samsara-fn init <name> --zipFile ./dist/src.zip --handler entrypoint.main --parameters params.json --secrets .secret.jsonSeed a local project
samsara-fn run manual|api|schedule|alertActionSimulate triggers; prints return values for debugging
samsara-fn schemasList JSON schemas for config validation
samsara-fn dependencies latest --installInstall the curated runtime dependencies locally

Note: the simulator uses alertAction as the run mode name; production uses alert as the trigger source value.

A practical local flow:

  1. Start from the just-secrets template to validate secrets retrieval.
  2. Bundle into a zip and review warnings.
  3. Initialize the Function locally.
  4. Run locally (for example, samsara-fn run manual) to confirm parameter parsing and logging.
  5. Align dependency expectations with samsara-fn dependencies latest when vendoring dependencies.

The dashboard has a Show help? panel on every Functions tab with CLI setup steps.

Best practices

Do:

  • Finish well under 15 minutes; measure and budget time. Split multi-step pipelines across triggers (for example, enqueue on alert, process on schedule).
  • Make handlers idempotent — safe to re-invoke. Checkpoint progress with Storage or the key-value database.
  • Log the correlation ID early and on completion.
  • Use HTTPS for third-party calls; handle non-200 responses.
  • Retrieve secrets at runtime; keep them out of code and event parameters.
  • Vendor extra Python dependencies in the zip; pin versions in a requirements.txt used by your vendoring script.
  • Namespace Storage/DB keys clearly; clean up temporary artifacts.
  • Validate via manual or API runs and confirm logs before enabling alerts or schedules broadly.
  • Document required parameters and secret keys in your Function's description or README.

Don't:

  • Log plaintext secrets or store secrets in Storage.
  • Assume retries — there are none. Design for re-invocation instead.
  • Rely on return values; log outcomes instead.
  • Exceed the 50 MB zip limit; avoid bundling unused files.
  • Block on long polls without limits; avoid unbounded loops and sleeps.
  • Depend on custom environment variables or custom Lambda layers (unsupported).

Troubleshooting

SymptomWhat to check
Function fails immediatelyLogs for stack traces; handler path matches module.function; missing secrets
No logs visibleNarrow the time range; confirm the run completed; search by correlation ID
Timeout after 15 minutesOptimize loops or batch work; split into smaller jobs across triggers
Cannot use as alert actionFunction visibility must allow customer access
API calls failCorrect regional base URL; token scopes (Functions > Write to trigger runs)

For additional help:

FAQ

Are languages other than Python supported?
Only Python (3.12) is supported today for Function code packages.

Can I run the same Function code in multiple regions?
Functions are deployed per organization in that organization's cloud region. If you operate in multiple regions, create and deploy Functions separately in each region's dashboard, and point API calls at the matching regional base URL.

How is this different from a Marketplace app or API token integration?
Marketplace apps use OAuth for customer installs and are suited for productized partner integrations. Functions are for custom code that runs inside Samsara — ideal for automations, single-org workflows, and rapid prototyping that calls the same APIs you would use from an external service.

Related guides