> 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 API authentication

> Authenticate against the Mammoth API with an API token sent as a Bearer header. Base URL, credential storage, and how to sign in without a terminal.

Scripts, the REST API and the SDK use an API token, sent as `Authorization: Bearer mm_...`. MCP clients and the CLI's browser sign-in use OAuth instead. Browser sessions use JWTs, which are not available to an integration.

## Which credential for which surface

| You are using | Credential | How you get it |
| --- | --- | --- |
| REST API, `mammoth-io` SDK, scripts and CI | `mm_` API token, sent as a Bearer header | **Workspace settings → API Tokens → Create token**, described below |
| The `mammoth` CLI, on your own machine | A browser sign-in, or a device code on a machine with no browser | `mammoth auth login --method oauth`, or `mammoth auth login --method device` |
| The CLI in CI or any unattended run | The same `mm_` API token | `mammoth auth login --method token`, or `--input creds.json` |
| The Mammoth MCP server, `https://mcp.mammoth.io/mcp` | OAuth, through your MCP client | The client opens a Mammoth consent page. See [Mammoth MCP server](https://docs.mammoth.io/agents/mcp) |

A token made by hand in Workspace settings does not work against the MCP server: the server accepts only tokens issued by the OAuth sign-in. See [the OpenAPI document](https://app.mammoth.io/api/v2/docs/openapi.json) for the full REST reference.

> **Keep credentials out of your code**
>
> For the SDK and curl, keep the token in an environment variable: never in a prompt, a script, or a file in the repository. The CLI does not read environment variables at all.

## Sign in to the CLI without a token

`mammoth auth login` asks how to sign in, or you pass the method:

| Command | What happens |
| --- | --- |
| `mammoth auth login --method oauth` | Opens your browser to Mammoth's consent page. The CLI stores a short-lived token and refreshes it for you. `--no-browser` prints the sign-in URL instead of opening it. |
| `mammoth auth login --method device` (or `--device`) | For a machine with no browser. The CLI prints a short code and a URL; you approve on any other device and the CLI waits. |
| `mammoth auth login --method token` | Prompts for an `mm_` API token with hidden input. |

`mammoth auth logout` signs out and also revokes the connection on the server.

OAuth access tokens last one hour, and the CLI refreshes them for you. Refresh tokens rotate on every use and have no expiry of their own. See [how long sign-in lasts](https://docs.mammoth.io/agents/mcp#how-long-sign-in-lasts) for the details.

## Connected apps and revoking access

When you sign in to an MCP client or to the CLI with OAuth, Mammoth shows a consent page. You choose the workspace and a project (or all projects) and approve. The app can then read and change data in that scope as you, the same as an API token, and cannot read your other workspaces.

To remove access, open **Settings → Connected apps** in the web app and choose **Revoke** next to the app. It loses access at once, including for anything it is doing at that moment. You can connect it again from the app.

## Get your credentials

You need one value: an **API token**.

1. Open the Mammoth web app.
2. Go to **Workspace settings → API Tokens** and choose **Create token**.
3. **Copy the token immediately**: it starts with `mm_` and is shown once. If you lose it, create a new one.

A token works only in the workspace and on the server where you created it, and it names that workspace itself. Neither the SDK nor the CLI asks you for a workspace id. You need the id only to write a REST URL such as `/workspaces/{id}/projects`: it is the number after `/workspaces/` in the web app's address bar.

> **Project-limited tokens**
>
> A token can be limited to one project when you create it. It then gets HTTP 403 in every other project, including a project it created. Create the token without a project if your code creates or switches projects.

> **API access works the same on every plan**
>
> A token behaves identically regardless of which plan you're on. What changes with the plan is what sits behind the token: storage, how many builders you have, and how often data refreshes. A workspace with a token has the same limits it has in the browser.

## Base URL

```
https://app.mammoth.io/api/v2
```

`app` is the default server prefix and names your region. If your Mammoth runs on a different prefix, substitute it: `https://<prefix>.mammoth.io/api/v2`.

## Headers

Every request carries one header.

| Header | Value |
| --- | --- |
| `Authorization` | `Bearer mm_...`, your API token |

A token belongs to one workspace, so you don't send a workspace header with it. If a request does name a workspace (an `X-WORKSPACE-ID` header, or the workspace id in the URL path), it must be the token's own workspace, or the API returns 401. Only the deprecated key and secret headers require `X-WORKSPACE-ID`.

> **X-API-KEY and X-API-SECRET are deprecated**
>
> The API still accepts the older key and secret headers, but new tokens have no secret. Use the Bearer token for anything new.


**curl**

```bash
curl https://app.mammoth.io/api/v2/workspaces/$MAMMOTH_WORKSPACE_ID/projects \
  -H "Authorization: Bearer $MAMMOTH_API_TOKEN"
```

**mammoth-io**

```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)
        await client.projects.list()


asyncio.run(main())
```

**CLI**

```bash
mammoth auth login            # prompts for the token; the workspace comes from the token

# No terminal (agents, CI):
mammoth auth login --input creds.json --storage file --output json --no-input
```


The SDK and the CLI add this header for you. The SDK is async (see [Python SDK](https://docs.mammoth.io/build/sdk)). It takes only the token, because a token names its own workspace; passing `workspace_id` with a token is an error. Most operations also need a project; set it with `client.set_project_id(…)`.

## Keep credentials out of your code

For the SDK and curl, use environment variables. Never hard-code a token, never put one in a prompt, and never commit one.

```bash
export MAMMOTH_API_TOKEN="mm_<your-token>"
export MAMMOTH_WORKSPACE_ID="<your-workspace-id>"   # only for REST URLs, as in the curl example
```

For agents and CI, which cannot answer hidden prompts, sign in from an owner-only file outside the repository:

**`creds.json`**

```json
{
  "api_token": "mm_<your-token>",
  "server_prefix": "app"
}
```

`api_token` is required. `server_prefix` is optional and defaults to `app`. The file takes no other field; a `workspace_id` in it is rejected.

Create the file owner-only (`0600`) from the start, for example from your CI secret store; don't write it first and `chmod` it afterwards, because another process may already have read it. The CLI refuses a group- or world-readable file.

```bash
mammoth auth login --input creds.json --storage file --output json --no-input
```

`--storage file` is explicit because `--storage auto`, the default, picks the OS keyring and fails in a process that has none. To target a different region, pass `--server-prefix LABEL`. Delete the file once the credentials are stored.

> **The CLI has no environment-variable shortcut**
>
> `MAMMOTH_API_TOKEN` is how the **Python SDK** gets its token, because you pass it to the client yourself. The **CLI** never reads it: it uses the credentials you stored above, from the keyring or from a credentials file.

## Finding ids from a URL

The SDK can pull ids straight out of an app 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}
```

## When authentication fails

A bad or missing credential returns **HTTP 401**. The SDK raises `MammothAuthError`; the CLI exits with code **4**.

> **Not retryable**
>
> Neither is worth retrying. Re-check the token instead. A project-limited token gets HTTP 403, not 401, outside its project. The CLI shows such a token only its own project: `project list` lists that one project, and `project get OTHER_ID` is refused locally with `authorization_required`. The only CLI exit code worth a retry is `7`.

## Next up

- [Quickstart](https://docs.mammoth.io/build/quickstart): your first real call, three ways.
- [Command contract](https://docs.mammoth.io/build/): everything you can do, with its blast radius.

---
Source: https://docs.mammoth.io/build/auth.md · Updated: 2026-10-15