---
sidebar_position: 999
title: Creating a new integration
description: Guidelines for integrating your application with MotherDuck, including connection strings and custom user agent configuration.
---

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

Integrating with MotherDuck follows the same pattern as integrating with DuckDB, so you can use the same client APIs and frameworks.

There are three differences:

1. Use `md:` or `md:analytics` as the connection string instead of a local filesystem path.
2. Pass `motherduck_token` through a config dictionary, connection string parameter, or environment variable.
3. Pass `custom_user_agent` so MotherDuck can identify the integration in query history.

### Choose a `custom_user_agent` format {#custom-user-agent-format}

Use the format `integration/version(metadata1,metadata2)`. The version and metadata sections are optional.

- Avoid spaces in the integration and version sections.
- Separate multiple metadata values with commas.
- If you plan to group by one workload label later, put it first in the metadata list.

Examples:

- `catalogsync`
- `catalogsync/5.1.5.1`
- `catalogsync/5.1.5.1(batchload)`
- `catalogsync/5.1.5.1(batchload,useast1)`

## Language and framework examples {#custom-user-agent-examples}

<Tabs groupId="integration-language">
  <TabItem value="python" label="Python" default>

```python
con = duckdb.connect("md:analytics", config={
    "motherduck_token": token,
    "custom_user_agent": "catalogsync/5.1.5.1(batchload,useast1)"
})
```

  </TabItem>
  <TabItem value="sqlalchemy" label="SQLAlchemy">

```python
eng = create_engine("duckdb:///md:analytics", connect_args={
    "config": {
        "motherduck_token": token,
        "custom_user_agent": "catalogsync/5.1.5.1(batchload,useast1)"
    }
})
```

  </TabItem>
  <TabItem value="java" label="Java / JDBC">

```java
Properties config = new Properties();
config.setProperty("motherduck_token", token);
config.setProperty("custom_user_agent", "catalogsync/5.1.5.1(batchload,useast1)");
Connection mdConn = DriverManager.getConnection("jdbc:duckdb:md:analytics", config);
```

  </TabItem>
  <TabItem value="nodejs" label="Node.js">

```javascript
import { DuckDBInstance } from '@duckdb/node-api'

const instance = await DuckDBInstance.create("md:analytics", {
    motherduck_token: token,
    custom_user_agent: "catalogsync/5.1.5.1(batchload,useast1)"
})
const conn = await instance.connect()
```

  </TabItem>
  <TabItem value="go" label="Go">

```go
dsn := fmt.Sprintf(
    "md:analytics?motherduck_token=%s&custom_user_agent=%s",
    url.QueryEscape(token),
    url.QueryEscape("catalogsync/5.1.5.1(batchload,useast1)"),
)
db, err := sql.Open("duckdb", dsn)
```

  </TabItem>
</Tabs>

## Implementation best practices

If you use DuckDB or MotherDuck in a shared environment where one process serves multiple users, the connection string must be unique per user.

You can disambiguate the connection string with a user-specific parameter such as `md:analytics?session_user=<user_id>`.

If you pass `motherduck_token` in the connection string, ensure your application does not log it in plaintext.


---

## 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": "/integrations/how-to-integrate/",
  "page_title": "Creating a new integration",
  "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`).
