> AI agents: this is one page from Mammoth Analytics documentation. The index of all pages as Markdown is https://docs.mammoth.io/llms.txt. Append `.md` to any docs URL, or send `Accept: text/markdown`, to get Markdown.

# Mammoth Analytics Python SDK (mammoth-io)

> Install mammoth-io, create a client, work with Views, apply transformations and export results. Python 3.12 to 3.14.

`mammoth-io`. Build data pipelines, apply transformations, and export results from Python.

> **From other languages, use the REST API**
>
> There is no JavaScript or TypeScript SDK. Neither `@mammoth/sdk` (npm) nor `mammoth-sdk` (PyPI) is a Mammoth package. Call the REST API directly instead.

## Install

```bash
pip install mammoth-io
```

Or with Poetry:

```bash
poetry add mammoth-io
```

| | |
| --- | --- |
| Package | `mammoth-io` |
| Python | **3.12, 3.13, 3.14 only**. A user on 3.10 or 3.11 cannot install it. |
| Dependencies | `httpx`, `pydantic`, ranged rather than pinned |
| Optional extra | `bridge`, which pins its dependencies exactly |
| Licence | Proprietary. The repo is public to read, which is **not** the same as open source. |

> **Read PyPI for the version**
>
> No version number is printed on this page on purpose. The package ships often enough that a number written into documentation is stale within hours. Read it from the source of truth instead:
>
> `pip index versions mammoth-io`

## Create a client

The client is **async**: every call that talks to the API must be awaited. Run your code inside `asyncio.run(...)`, or `await` directly in a notebook. Pass only the API token: a token belongs to one workspace, so the client takes no `workspace_id` and rejects one. Most operations also need a project.

```python
import asyncio
import os

from mammoth import MammothClient


async def main():
    async with MammothClient(
        api_token=os.environ["MAMMOTH_API_TOKEN"],
    ) as client:
        client.set_project_id(10)
        projects = await client.projects.list()


asyncio.run(main())
```

The client sends your token as `Authorization: Bearer mm_...` on every request, against a default base URL of `https://app.mammoth.io/api/v2`. On first use it asks Mammoth which workspace the token belongs to and keeps the answer in `client.workspace_id`. `async with` closes its HTTP session when the block ends; without it, call `await client.close()` yourself. Constructing the client and `set_project_id` are synchronous.

The examples below run inside `main()` above.

Store credentials in environment variables. Never hard-code a token, never put one in a prompt, and never commit one—see [Authentication](https://docs.mammoth.io/build/auth).

### Getting ids out of a URL

```python
from mammoth import parse_path

ids = parse_path("https://app.mammoth.io/#/workspaces/11/projects/10/views/1039")
# {"workspace_id": 11, "project_id": 10, "dataview_id": 1039}
```

## Views are the object you work on

A **View** wraps a dataview and carries the transformation methods, the data accessors and the export helpers.

```python
view = await client.views.get(1039)

view.name           # "My View"
view.display_names  # ["Sales", "Region", "Date", ...]
view.column_types   # {"Sales": "NUMERIC", "Region": "TEXT", ...}
```

## Transformations apply in place

Each call sends a task to the Mammoth pipeline, waits for it to complete, and refreshes the view metadata. You do not assemble a plan and submit it; you act on the view.

```python
from mammoth import Condition, Operator, ColumnType, SetValue

# Filter rows
await view.filter_rows(Condition("Sales", Operator.GTE, 1000))

# Add a computed column
await view.set_values(
    new_column="Category",
    column_type=ColumnType.TEXT,
    values=[
        SetValue("High", condition=Condition("Sales", Operator.GTE, 10000)),
        SetValue("Low"),
    ],
)

# Math expression
await view.math("Price * Quantity", new_column="Total")
```

### Rename and sort are display settings

Renaming a column and sorting rows are the web grid's own actions, not pipeline tasks. They change how the view presents its data, and later reads, exports, and dashboards follow them.

```python
await view.rename_columns({"cust_ref": "Customer Ref"})
await view.sort_rows([["Sales", "DESC"], ["Region", "ASC"]])  # up to three columns; [] clears
```

A renamed column keeps its internal name, so pipeline tasks that already use it keep working, and later calls refer to it by the new name.

## Export

```python
await view.export.to_csv("output.csv")
await view.export.to_s3(...)
await view.export.to_postgres(...)
```

## Working with resources

```python
await client.projects.list()        # {"projects": [...], "offset": 0, ...}
await client.datasets.list()
await client.files.upload(...)
```

Note the shape of a list response: the resource collection plus paging fields. See [pagination](https://docs.mammoth.io/build/pagination).

## Errors

- `MammothAuthError` on HTTP 401. Not retryable: check the token.
- Never hard-code credentials. Read them from the environment, as above.

## Next up

- [The CLI](https://docs.mammoth.io/build/cli/)—built on this SDK, with discovery and safety on top.
- [Command contract](https://docs.mammoth.io/build/)—every SDK method with its CLI command and blast radius.
- [Authentication](https://docs.mammoth.io/build/auth)—headers, base URL, regions, credential storage.
- [Errors and exit codes](https://docs.mammoth.io/build/errors)—what the API returns and what is worth retrying.

---
Source: https://docs.mammoth.io/build/sdk.md · Updated: 2026-10-13