> For the complete documentation index, see [llms.txt](https://dnotifier.gitbook.io/product-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dnotifier.gitbook.io/product-docs/getting-started/credentials.md).

# Credentials & environment

DNotifier SDKs authenticate with three core values: **appId**, **secret**, and **userId**. This page explains each one and shows how to load them safely in your application.

## The three credentials

### appId

Your application's public identifier, created in the dashboard when you [**create an app**](/product-docs/getting-started/create-app.md).

* Passed to the SDK constructor as `appId`
* Used in auth requests and message routing
* Not secret by itself, but tie it to the correct environment (dev vs production)

### secret

Your application's private key, paired with `appId`.

* Passed to the SDK constructor as `secret`
* Sent to DNotifier during `connect()` authentication
* **Must never be committed to git**, logged, or exposed in client-side bundles unless you accept the security tradeoff

If a secret leaks, rotate it immediately in the dashboard and update your deployment environment.

### userId

An identifier for the **end user** or **service account** connecting through your app.

* Passed to the SDK constructor as `userId`
* Used for auth, routing, and per-user limits
* You choose the format — common patterns:
  * Database primary key: `user_8f3a2b`
  * Auth provider subject: `google-oauth2|1029384756`
  * Service name: `backend-worker-1`

The SDK prefixes `userId` with your `appId` internally when addressing messages, so two apps can use the same raw `userId` without collision.

## Never commit secrets

Add secret files to `.gitignore` before your first commit:

```gitignore
.env
.env.local
.env.*.local
*.pem
secrets/
```

Use placeholder values in example code and documentation:

```js
appId: process.env.DNOTIFIER_APP_ID,
secret: process.env.DNOTIFIER_SECRET,  // never hard-code
userId: "user-123",
```

## Environment variable pattern

### Node.js / JavaScript

```bash
# .env
DNOTIFIER_APP_ID=abc123your-app-id
DNOTIFIER_SECRET=your-secret-here
```

```js
import { DNotifier } from "@dnotifier-realtime/dnotifier";

const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "ws",
  userId: "user-123",
  onConnected: () => {},
  onMessage: () => {},
  onDisconnected: () => {},
});
```

Use `dotenv` or your framework's built-in env loading (Next.js, Vite, etc.).

### Dart / Flutter

```bash
# .env (load with flutter_dotenv or similar)
DNOTIFIER_APP_ID=abc123your-app-id
DNOTIFIER_SECRET=your-secret-here
```

```dart
import 'package:dnotifier/dnotifier.dart';

final notifier = DNotifier(
  appId: const String.fromEnvironment('DNOTIFIER_APP_ID'),
  secret: const String.fromEnvironment('DNOTIFIER_SECRET'),
  transport: 'ws',
  userId: 'user-123',
  onConnected: () {},
  onMessage: (_) {},
);
```

For Flutter, `--dart-define` flags or a secrets plugin are common in production builds.

## Where to put secrets by deployment target

| Target             | Recommendation                                                             |
| ------------------ | -------------------------------------------------------------------------- |
| Node.js server     | Environment variables or secret manager (AWS Secrets Manager, Vault, etc.) |
| Browser (dev only) | Avoid embedding `secret` in frontend bundles in production                 |
| Flutter mobile     | `--dart-define`, native secure storage, or CI-injected secrets             |
| CI/CD              | Inject `DNOTIFIER_APP_ID` and `DNOTIFIER_SECRET` as protected variables    |

For production browser apps, authenticate users on your backend and issue scoped tokens rather than shipping the app secret to every client.

## Checklist

* [ ] `appId` and `secret` come from the dashboard, not hard-coded strings
* [ ] `.env` is in `.gitignore`
* [ ] CI uses masked environment variables
* [ ] `userId` is stable for each user across sessions
* [ ] Dev and production use different apps (and secrets)

## Next steps

* [**Choose your transport**](/product-docs/getting-started/choose-transport.md) — WebSocket vs HTTP
* [**Install an SDK**](/product-docs/getting-started/installation.md) — Package installation guides
* [**Your first connection**](/product-docs/getting-started/first-connection.md) — Connect with real credentials
