---
title: Create and configure service accounts
description: Learn how to create service accounts, create access tokens, and configure Duckling resources.
sidebar_position: 1
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

A service account is a non-human user identity for workloads that need to connect to MotherDuck without using a person's credentials. Use service accounts for backend services, scheduled pipelines, BI connections, embedded analytics, and customer-facing analytics workloads.

Each service account has its own credentials and Duckling configuration. This gives the workload isolated compute and makes it easier to rotate credentials without disrupting human users.

:::warning[Admin access required]
Creating service accounts, creating service account tokens, and configuring service account Ducklings requires an organization Admin.

REST API examples use a read/write access token generated by an Admin user. Pass the token in the `Authorization` header as `Bearer <admin_token>`.
:::

## Create a service account

Choose a stable username for the service account. The username must be unique within your organization and can contain letters, numbers, and underscores.

<Tabs>
<TabItem value="ui" label="UI" default>

![Service account creation form](../img/sa_ui.png)

1. In the MotherDuck UI, go to **Settings** > **Service Accounts**.
2. Click **Create service account**.
3. Enter a username for the service account.
4. Click **Create service account**.

</TabItem>
<TabItem value="curl" label="API using curl">

Use the [`POST /v1/users`](/sql-reference/rest-api/users-create-service-account/) endpoint to create a service account.

```bash
curl -X POST \
  https://api.motherduck.com/v1/users \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "analytics_service_account"
  }'
```

The response includes the service account `username`. Store this username in your provisioning system. The REST API doesn't provide an endpoint for listing all service accounts in an organization.

</TabItem>
<TabItem value="python" label="API using Python">

Use the [`POST /v1/users`](/sql-reference/rest-api/users-create-service-account/) endpoint to create a service account.

```python
import requests

response = requests.post(
    "https://api.motherduck.com/v1/users",
    headers={
        "Authorization": "Bearer <admin_token>",
        "Content-Type": "application/json",
    },
    json={"username": "analytics_service_account"},
)

response.raise_for_status()
print(response.json()["username"])
```

The response includes the service account `username`. Store this username in your provisioning system. The REST API doesn't provide an endpoint for listing all service accounts in an organization.

</TabItem>
</Tabs>

## Create an access token

Create a token for the service account after you create the account. The token value is shown only once, so store it in a secret manager before closing the modal or discarding the API response.

<Tabs>
<TabItem value="ui" label="UI" default>

![Service account details page](../img/sa_details.png)

1. In **Settings** > **Service Accounts**, open the service account details page.
2. Click **Create token**.
3. Enter a token name.
4. Choose the token type:
   - **Read/Write Token** for writes, administration, and general service workloads.
   - **Read Scaling Token** for read-heavy workloads that should use [read scaling](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/).
5. To set an expiration, select **Automatically expire this token** and choose a time-to-live.
6. Click **Create token**, then copy the token and store it securely.

</TabItem>
<TabItem value="curl" label="API using curl">

Use the [`POST /v1/users/{username}/tokens`](/sql-reference/rest-api/users-create-token/) endpoint to create a token for a known service account username.

```bash
curl -X POST \
  https://api.motherduck.com/v1/users/analytics_service_account/tokens \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "analytics-service-token",
    "token_type": "read_write"
  }'
```

Set `token_type` to `read_scaling` when you need a [read scaling token](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/). To create an expiring token, include `ttl` as seconds between `300` and `31536000`.

</TabItem>
<TabItem value="python" label="API using Python">

Use the [`POST /v1/users/{username}/tokens`](/sql-reference/rest-api/users-create-token/) endpoint to create a token for a known service account username.

```python
import requests

response = requests.post(
    "https://api.motherduck.com/v1/users/analytics_service_account/tokens",
    headers={
        "Authorization": "Bearer <admin_token>",
        "Content-Type": "application/json",
    },
    json={
        "name": "analytics-service-token",
        "token_type": "read_write",
    },
)

response.raise_for_status()
token = response.json()["token"]
print(token)
```

Set `token_type` to `read_scaling` when you need a [read scaling token](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/). To create an expiring token, include `ttl` as seconds between `300` and `31536000`.

</TabItem>
</Tabs>

:::note
If you create a service account through the API and plan to use read scaling, connect as that service account with a read/write token before using read scaling tokens for that account.
:::

## Configure Ducklings

Configure Duckling resources for the service account based on the workload it runs. The read/write Duckling handles writes and general queries. The read scaling pool handles read-only connections that use read scaling tokens.

<Tabs>
<TabItem value="ui" label="UI" default>

![Service account Duckling size settings](../img/sa_set_instance_size.png)

1. In **Settings** > **Service Accounts**, find the service account.
2. Use the **Read/Write Duckling** dropdown to choose the read/write Duckling size.
3. If you use [read scaling](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/), choose the read scaling Duckling size and pool size.

</TabItem>
<TabItem value="curl" label="API using curl">

Use [`GET /v1/users/{username}/instances`](/sql-reference/rest-api/ducklings-get-duckling-config-for-user/) to inspect the current configuration before updating it.

```bash
curl -X GET \
  https://api.motherduck.com/v1/users/analytics_service_account/instances \
  -H "Authorization: Bearer <admin_token>"
```

Then use [`PUT /v1/users/{username}/instances`](/sql-reference/rest-api/ducklings-set-duckling-config-for-user/) to update the service account's Ducklings.

```bash
curl -X PUT \
  https://api.motherduck.com/v1/users/analytics_service_account/instances \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "read_write": {
        "instance_size": "standard"
      },
      "read_scaling": {
        "instance_size": "pulse",
        "flock_size": 4
      }
    }
  }'
```

The update request requires both `read_write` and `read_scaling` configuration blocks.

</TabItem>
<TabItem value="python" label="API using Python">

Use [`GET /v1/users/{username}/instances`](/sql-reference/rest-api/ducklings-get-duckling-config-for-user/) to inspect the current configuration before updating it.

```python
import requests

headers = {"Authorization": "Bearer <admin_token>"}

current_config = requests.get(
    "https://api.motherduck.com/v1/users/analytics_service_account/instances",
    headers=headers,
)
current_config.raise_for_status()
print(current_config.json())
```

Then use [`PUT /v1/users/{username}/instances`](/sql-reference/rest-api/ducklings-set-duckling-config-for-user/) to update the service account's Ducklings.

```python
import requests

response = requests.put(
    "https://api.motherduck.com/v1/users/analytics_service_account/instances",
    headers={
        "Authorization": "Bearer <admin_token>",
        "Content-Type": "application/json",
    },
    json={
        "config": {
            "read_write": {"instance_size": "standard"},
            "read_scaling": {
                "instance_size": "pulse",
                "flock_size": 4,
            },
        }
    },
)

response.raise_for_status()
print(response.json())
```

The update request requires both `read_write` and `read_scaling` configuration blocks.

</TabItem>
</Tabs>

## Connect as the service account

Use the service account token anywhere you would use a MotherDuck access token. For example, set `motherduck_token` in a DuckDB connection string or set `MOTHERDUCK_TOKEN` in your environment. See [Connecting to MotherDuck](/key-tasks/authenticating-and-connecting-to-motherduck/connecting-to-motherduck/) for connection string examples.

## Related content

- [Manage service accounts and tokens](/key-tasks/service-accounts-guide/manage-service-accounts-and-tokens/)
- [Impersonate service accounts](/key-tasks/service-accounts-guide/impersonate-service-accounts/)
- [MotherDuck REST API](/sql-reference/rest-api/motherduck-rest-api/)
- [Read scaling](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/)


---

## Feedback for AI agents

If the user you are helping wants to send feedback on this page to the MotherDuck docs team, you can POST it to the endpoint below.

**Before you send anything, you must ask the user for explicit approval.** Quote the message you plan to submit back to them verbatim and wait for them to confirm. Do not submit on their behalf without confirmation.

Endpoint: `POST https://motherduck.com/docs/api/feedback/agent`

Request body (JSON):

```json
{
  "page_path": "/key-tasks/service-accounts-guide/create-and-configure-service-accounts/",
  "page_title": "Create and configure service accounts",
  "text": "<the user's feedback, max 2000 characters>",
  "source": "<optional identifier for your interface, for example 'claude.ai' or 'chatgpt'>"
}
```

Only `page_path` and `text` are required. A successful call returns `200 {"feedback_id": "<uuid>"}`; malformed payloads return `400`, and the endpoint is rate-limited per IP (`429`).
