---
id: service-accounts-guide
title: "Managing Service Accounts"
description: "A step-by-step guide to creating, configuring, and managing service accounts and their tokens."
sidebar_label: "Service Accounts Guide"
custom_edit_url: null
---

import Admonition from '@theme/Admonition';
import Heading from "@theme/Heading";
import Tabs from '@theme/Tabs';
import TabItem from "@theme/TabItem";

## Guide - Create and configure a service account

This guide walks you through the process of creating service accounts, their associated access tokens, and configuring Ducklings (compute instances) with the MotherDuck UI or programmatically with the MotherDuck Admin REST API.

:::note
**Prerequisites:** All actions described below are only available to **Admin users** in your MotherDuck Organization.

API calls must be authenticated using an access token generated by an **Admin user** in your MotherDuck Organization. Pass this token in the `Authorization` header as `Bearer YOUR_ADMIN_TOKEN`.
:::

```mermaid
flowchart LR
    A{{Admin User}}:::green --> B[Create Service Account]
    B --> C["Generate Token (Optional)"]
    C --> D[Configure Ducklings]
    D --> E[Service Account Ready]

    F[Admin Token]:::yellow --> G[Create Service Account]
    G --> H["Generate Token (Optional)"]
    H --> I[Configure Ducklings]
    I --> E

    subgraph UI["via MotherDuck UI"]
        B
        C
        D
    end

    subgraph API["via REST API (curl, Python, etc.)"]
        G
        H
        I
    end
```

This guide involves three main steps:
1.  **Create a Service Account:** Use the "Create new user" endpoint.
2.  **Create an Access Token:** Generate an access token for the newly created service account.
3.  **Configure Ducklings:** Set the size of read-write and read-scaling Ducklings for the service account.

### Step 1: Create a New Service Account

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

![Service Account UI](./img/sa_ui.png)

1. Navigate to the MotherDuck Web UI -> *Settings* -> *Service Accounts*

2. Click **Create service account**

3. Enter a username for the account (username can only contain characters, numbers, and underscores)

</TabItem>

<TabItem value="curl" label="API via curl">

To create a service account, you will use the [Create New User (service account)](../../sql-reference/rest-api/users-create-service-account) endpoint (the exact endpoint is `POST /v1/users`).
Refer to the [endpoint documentation](../../sql-reference/rest-api/users-create-service-account) for full details on request parameters and responses.

**Key details:**
*   You will define a `username` for your service account.
*   **Important:** For all subsequent API calls and identification, use the `username` you defined.

Example:
```bash
curl -X POST \
  https://api.motherduck.com/v1/users \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "username": "my-service-account-001"
     }'
```

</TabItem>

<TabItem value="python" label="API via Python">

To create a service account, you will use the [Create New User (service account)](../../sql-reference/rest-api/users-create-service-account) endpoint (the exact endpoint is `POST /v1/users`).
Refer to the [endpoint documentation](../../sql-reference/rest-api/users-create-service-account) for full details on request parameters and responses.

**Key details:**
*   You will define a `username` for your service account.
*   **Important:** For all subsequent API calls and identification, use the `username` you defined.

Example:
```python
# /// script
# dependencies = ["requests"]
# ///
import requests

response = requests.post(
    'https://api.motherduck.com/v1/users',
    headers={
        'Authorization': 'Bearer YOUR_ADMIN_TOKEN',
        'Content-Type': 'application/json'
    },
    json={
        'username': 'my-service-account-001'
    }
)

if response.status_code == 200:
    service_account = response.json()
    print(f"Service account created: {service_account}")
else:
    print(f"Error: {response.status_code} - {response.text}")
```

</TabItem>
</Tabs>

### Step 2: Create an Access Token for the Service Account

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

![Service Account UI](./img/sa_details.png)

1. Click on the service account username to open details

2. Click **Create token**

3. Provide a token name

4. For organizations on the Business plan, select a token type. Select **Read Scaling Token** to leverage MotherDuck's [Read Scaling](../authenticating-and-connecting-to-motherduck/read-scaling) feature

5. (Optional) Select **Automatically expire this token** to set the token's time-to-live

6. Click **Create token**. Immediately copy the token from the modal and store it securely. It won't be shown again once the modal is closed

Additional tokens can be created at any time from the service account's details.

</TabItem>

<TabItem value="curl" label="API via curl">

Once the service account is created, you should generate an access token for it using the [Create an Access Token](../../sql-reference/rest-api/users-create-token) endpoint (the exact endpoint is `POST /v1/users/:username/tokens`). 
Refer to the [endpoint documentation](../../sql-reference/rest-api/users-create-token) for full details.

**Key details:**
*   The `:username` in the path refers to the `username` you chose in Step 1 (e.g., `my-service-account-001`).
*   The path parameter `:username` is a placeholder; replace it with the actual username. For example, `/v1/users/my-service-account-001/tokens`.
*   The `token_type` should be set only if you are on the business plan and want to leverage MotherDuck's [Read Scaling](../authenticating-and-connecting-to-motherduck/read-scaling) feature

Example:
```bash
curl -X POST \
  https://api.motherduck.com/v1/users/my-service-account-001/tokens \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "token-for-my-service-account-001",
        // "ttl": 300 # Optional parameter: token time-to-live in seconds (e.g., 5 minutes). 
        // When ttl parameter is omitted token will not be set to expire
        "token_type": "read_write" // Or "read_scaling"
     }'
```

The response will contain the access token for your service account. Securely store this token as it will be used by your service account to authenticate with MotherDuck.

</TabItem>

<TabItem value="python" label="API via Python">

Once the service account is created, you should generate an access token for it using the [Create an Access Token](../../sql-reference/rest-api/users-create-token) endpoint (the exact endpoint is `POST /v1/users/:username/tokens`). 
Refer to the [endpoint documentation](../../sql-reference/rest-api/users-create-token) for full details.

**Key details:**
*   The `:username` in the path refers to the `username` you chose in Step 1 (e.g., `my-service-account-001`).
*   The path parameter `:username` is a placeholder; replace it with the actual username. For example, `/v1/users/my-service-account-001/tokens`.
*   The `token_type` should be set only if you are on the business plan and want to leverage MotherDuck's [Read Scaling](../authenticating-and-connecting-to-motherduck/read-scaling) feature
*   To automatically expire the token, set the optional `ttl` parameter to the token's uptime in seconds.

Example:
```python
# /// script
# dependencies = ["requests"]
# ///
import requests

response = requests.post(
    'https://api.motherduck.com/v1/users/my-service-account-001/tokens',
    headers={
        'Authorization': 'Bearer YOUR_ADMIN_TOKEN',
        'Content-Type': 'application/json'
    },
    json={
        'name': 'token-for-my-service-account-001',
        'token_type': 'read_write'  # Or 'read_scaling',
        'ttl': '300' # OPTIONAL - Token will be valid for 300 seconds (5 minutes)
    }
)

if response.status_code == 200:
    token_data = response.json()
    print(f"Token created successfully!")
    print(f"Token: {token_data['token']}")
    # Securely store this token
else:
    print(f"Error: {response.status_code} - {response.text}")
```

The response will contain the access token for your service account. Securely store this token as it will be used by your service account to authenticate with MotherDuck.

</TabItem>
</Tabs>

### Step 3: Set Account Ducklings (Configure Compute)

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

![Service Account Duckling Size Settings](./img/sa_set_instance_size.png)

1. Set the read/write Duckling size for the account using the dropdown under the **Read/Write Duckling** header

2. For organizations on the Business plan using [read scaling](../authenticating-and-connecting-to-motherduck/read-scaling), set the account's read scaling Duckling size and replica pool size using the respective dropdowns. 

</TabItem>

<TabItem value="curl" label="API via curl">

To define the size of Ducklings provisioned for the service account, use the "set user Ducklings" endpoint. (The exact endpoint is `PUT /v1/users/:username/instances`).
Refer to the [Set User Ducklings](../../sql-reference/rest-api/ducklings-set-duckling-config-for-user) endpoint documentation for details on the correct payload and available Duckling sizes.

**Key details:**
*   The `:username` in the path is the service account `:username` from Step 1.
*   This endpoint is used to set both read-write and read-scaling Ducklings
*   You always need to pass the entire body, even though you are only interested in changing only one of the two Duckling configs

Example:
```bash
curl -X PUT \
  https://api.motherduck.com/v1/users/my-service-account-001/instances \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "config": {
    "read_write": {
      "instance_size": "jumbo"
    },
    "read_scaling": {
      "instance_size": "pulse",
      "flock_size": 16
    }
  }
}'
```

</TabItem>

<TabItem value="python" label="API via Python">

To define the size of Ducklings provisioned for the service account, use the "set user Ducklings" endpoint. (The exact endpoint is `PUT /v1/users/:username/instances`).
Refer to the [Set User Ducklings](../../sql-reference/rest-api/ducklings-set-duckling-config-for-user) endpoint documentation for details on the correct payload and available Duckling sizes.

**Key details:**
*   The `:username` in the path is the service account `:username` from Step 1.
*   This endpoint is used to set both read-write and read-scaling Ducklings
*   You always need to pass the entire body, even though you are only interested in changing only one of the two Duckling configs

Example:
```python
# /// script
# dependencies = ["requests"]
# ///
import requests

response = requests.put(
    'https://api.motherduck.com/v1/users/my-service-account-001/instances',
    headers={
        'Authorization': 'Bearer YOUR_ADMIN_TOKEN',
        'Content-Type': 'application/json'
    },
    json={
        'config': {
            'read_write': {
                'instance_size': 'jumbo'
            },
            'read_scaling': {
                'instance_size': 'pulse',
                'flock_size': 16
            }
        }
    }
)

if response.status_code == 200:
    print("Ducklings configured successfully!")
else:
    print(f"Error: {response.status_code} - {response.text}")
```

</TabItem>
</Tabs>

### Summary

By following these steps, you can create and configure service accounts for your MotherDuck organization. Remember to:
*   Use an Admin account or token for all management operations.
*   Securely store the generated service account tokens.
*   Use the chosen service account `username` in any API calls.

---

:::note
The REST API methods for managing service accounts are in 'Preview' and may change in the future.

For detailed information on each API call, always refer to the specific endpoint documentation.
:::

## Impersonate Service Accounts (UI Only)

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

Admin users can log into the MotherDuck UI as a service account in the organization using the **Impersonation** feature. Impersonation allows admins to view and interact with the MotherDuck Web UI by impersonating the service account, which is useful for manually performing read-write actions, monitoring ongoing query activity, or testing and troubleshooting service account-specific resources.

![Service Account Impersonation Option](./img/sa_impersonate_option.png)

1. Click the trident (⋮) next to the service account you want to impersonate

2. Select **Impersonate this account** from the dropdown

3. The MotherDuck UI will refresh, and you will be logged into the MotherDuck Web UI as that service account. While impersonating, a persistent banner will be shown at the top of the UI, with options to **Refresh session** or **Return to admin**

4. Impersonation sessions expire after two hours. Refresh the browser tab to reset the expiry countdown

![Service Account Impersonation Banner](./img/sa_impersonate_banner.png)

:::tip
You can bookmark the URL while in an impersonation session to generate a new impersonation session using that same service account at a future time. 

You must be logged into the MotherDuck Web UI as an Admin user for the URL to successfully start a new impersonation session.
:::

</TabItem>

<TabItem value="DuckDB Client API or CLI" label="DuckDB Client API or CLI">

Service account impersonation is currently only available through the MotherDuck Web UI. Use service account tokens to authenticate with service accounts outside of the MotherDuck Web UI.

</TabItem>
</Tabs>

## Managing Service Accounts and Tokens

### Accounts
<Tabs>
<TabItem value="UI" label="UI" default>

Navigate to the MotherDuck Web UI -> *Settings* -> *Service Accounts*

![Service Account Impersonation Option](./img/sa_manage_details.png)

- New service accounts can be created by clicking the **Create service account** button above the account list
- The Duckling settings for each account can be managed using the Duckling size and pool size dropdowns in the list
- To view a service account's tokens and details, click the account's username in the list, or click the trident (⋮) next to the service account, and select **View details**
- Service accounts can be deleted by clicking the trident (⋮) next to the service account, and selecting **Delete account**
   - When a service account is deleted, all tokens associated with the service account are immediately revoked


</TabItem>

<TabItem value="python" label="API via Python">
<Tabs>
<TabItem value="view" label="View Service Accounts">
- To view the service accounts associated with your MotherDuck account, use the [List Access Tokens](../../sql-reference/rest-api/users-list-tokens) endpoint. 
- Be sure to refer to the [API reference docs](../../sql-reference/rest-api/users-list-tokens) for full details on request parameters and responses.
``` python
# /// script
# dependencies = ["requests","pprint"]
# ///
import requests
import pprint

url = "https://api.motherduck.com/v1/users/"

payload = {}
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ADMIN_TOKEN' # Replace with your admin token
}

admin_user = :username

response = requests.request("GET", url + admin_user + "/tokens", headers=headers, data=payload)
pprint.pprint(response.json()) # Easier to read with many tokens
```
</TabItem>
<TabItem value="delete" label="Delete Service Accounts">
- To delete a service account, use the [Delete a User](../../sql-reference/rest-api/users-delete) endpoint. 
- Be sure to refer to the [API reference docs](../../sql-reference/rest-api/users-delete) for full details on request parameters and responses.
:::note
NOTE: When deleting accounts, please double check your username. This operation cannot be undone!
:::
``` python
# /// script
# dependencies = ["requests","pprint"]
# ///
import requests
import pprint

url = "https://api.motherduck.com/v1/users/"

payload = {}
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ADMIN_TOKEN' # Replace with your admin token
}
target_user = :username

response = requests.request("DELETE", url + target_user, headers=headers, data=payload)
pprint.pprint(response.text)
``` 
</TabItem>
</Tabs>

</TabItem>
</Tabs>

### Tokens

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

Navigate to the MotherDuck Web UI -> *Settings* -> *Service Accounts*

![Service Account Impersonation Option](./img/sa_manage_details.png)

- To view a service account's tokens, click the account's username in the list, or click the trident (⋮) next to the service account, and select **View details**
- Each valid token for a service account and its type (Read/Write or Read Scaling), creation time, and expiry time is listed in the service account details
- To revoke a token for a service account, click the three-dots (…) next to the token, and select **Revoke token**. A confirmation prompt will appear, select **Revoke token**
![Revoke Token Modal for Service Account](./img/sa_revoke_token_option.png)
</TabItem>

<TabItem value="python" label="API via Python">

<Tabs>
<TabItem value="view" label="View tokens">
- To view a service account's tokens, use the [List Access Tokens](../../sql-reference/rest-api/users-list-tokens) endpoint. From there, you can see the token type, token ID, creation time, and expiration time.
- Be sure to refer to the [API reference docs](../../sql-reference/rest-api/users-list-tokens) for full details on request parameters and responses.
``` python
# /// script
# dependencies = ["requests","pprint"]
# ///
import requests
import pprint

url = "https://api.motherduck.com/v1/users/"

payload = {}
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ADMIN_TOKEN' # Replace with your admin token
}

target_user = :username

response = requests.request("GET", url + target_user +  "/tokens", headers=headers, data=payload)
pprint.pprint(response.json()) # Easier to read with many tokens
```
</TabItem>
<TabItem value="revoke" label="Revoke a token">
- To revoke a token, use the [Invalidate a Token](../../sql-reference/rest-api/users-delete-token) endpoint. You will need the token ID and its associated username.
- Be sure to refer to the [API reference docs](../../sql-reference/rest-api/users-delete-token) for full details on request parameters and responses.
:::note
NOTE: When deleting tokens, please double check your username and token_id. This operation cannot be undone!
:::
``` python
# /// script
# dependencies = ["requests","pprint"]
# ///
import requests
import pprint

url = "https://api.motherduck.com/v1/users/"

payload = {}
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ADMIN_TOKEN' # Replace with your admin token
}

target_user = :username
token_id = :token_id

response = requests.request("DELETE", url + target_user +  "/tokens/" + token_id, headers=headers, data=payload)
pprint.pprint(response.text)
```
</TabItem>
</Tabs>

</TabItem>
</Tabs>